2009-03-06 9 views
11

Aprendiendo Java, así que sea gentil por favor. Lo ideal es que necesito para crear una matriz de bytes que apuntará a una parte de un arreglo más grande:En Java: ¿dónde está la forma de crear un submatriz que apunte a una porción de una matriz más grande?

byte[] big = new byte[1000]; 

// C-style code starts 
load(file,big); 

byte[100] sub = big + 200; 

// C-style code ends 

Sé que esto no es posible en Java y hay dos soluciones temporales que vienen a la mente e incluiría:

  1. de cualquier proceso de copia de grande en sub iteración a través de grande.

  2. O escribiendo propia clase, que tendrá una referencia a gran tamaño + offset + y la aplicación de la "subconjunto" a través de métodos de acceso usando grande como la propia estructura de datos subyacente.

La tarea que estoy tratando de resolver es cargar un archivo en la memoria una a continuación, obtener acceso de sólo lectura a los registros almacenados en el canto del archivo a través de una clase. La velocidad es primordial, por lo tanto, idealmente me gustaría evitar los métodos de copiado o acceso. Y dado que estoy aprendiendo Java, me gustaría seguir con eso.

¿Alguna otra alternativa que tenga? Haga preguntas si no le expliqué la tarea lo suficientemente bien.

+0

Inconsistencia: byte [] sub = new byte [100]; reserva espacio para 100 bytes pero la asignación sub = grande + 200; solo almacena un puntero. –

+0

sganslandt, cierto. Movido al código de estilo C también. –

Respuesta

21

La creación de una matriz como una "vista" de otra matriz no es posible en Java. Pero podría usar java.nio.ByteBuffer, que es básicamente la clase que sugiere en el trabajo # 2. Por ejemplo:

ByteBuffer subBuf = ByteBuffer.wrap(big, 200, 100).slice().asReadOnlyBuffer(); 

No se produjo copia (aunque se crearon algunos objetos). Como una clase de biblioteca estándar, también supongo que ByteBuffer es más probable que reciba wrt de tratamiento especial.Optimizaciones "JIT" por la JVM que una personalizada.

1

Eche un vistazo a la fuente de java.lang.String (estará en src.zip o src.jar). Verás que tienen una variedad de Cahrs y luego un inicio y un final. Entonces, sí, la solución es usar una clase para hacerlo.

Here is a link to the source online.

Las variables de interés son:

  • valor
  • desplazamiento
  • recuento

subcadena es probablemente un buen método para mirar como punto de partida.

Si desea leer directlry del archivo, utilice la clase java.nio.channels.FileChannel, específicamente el método map(), que le permitirá utilizar las E/S asignadas de memoria, que serán muy rápidas y utilizarán menos memoria que la copia a matrices.

+0

Recuerde la implementación de String mientras lee un archivo enorme: los métodos de subcadena y división mantienen una referencia a la cadena original. Por lo tanto, si lee un archivo de 1 GB y almacena solo la primera palabra de cada línea, ¡el espacio necesario sigue siendo de 1 GB! – pihentagy

3

Si quiere leer un archivo rápido y con acceso de bajo nivel, consulte las cosas de java nio. Aquí hay un ejemplo del java almanac.

Puede utilizar un búfer de bytes asignado para navegar dentro del contenido del archivo.

+0

Gracias Miguel, pero parece que bajo el capó esta solución no combina 1 ni 2. –

0

Leer el archivo en la memoria es bueno, el archivo pronto es relativamente pequeño. Pero cuando tienes que lidiar con archivos enormes, mantenerlos fuera de la memoria es un objetivo mucho más deseado.

MappedByteBuffer es lo que estás buscando.

MappedByteBuffer es un búfer de byte directo cuyo contenido es una región asignada en memoria de un archivo. El contenido de un búfer de bytes asignado puede cambiar en cualquier momento, por ejemplo, si este programa u otro cambian el contenido de la región correspondiente del archivo asignado. Si estos cambios ocurren o no, y cuándo ocurren, depende del sistema operativo y, por lo tanto, no están especificados.

Cuestiones relacionadas