La matriz de bytes de Java contiene números negativos

Estoy leyendo un archivo en una matriz de bytes en fragmentos y enviándolo a través de la red a través de una solicitud POST a un servidor web. No es nada complicado, lo he hecho antes de usar este mismo código exacto. Esta vez, noté que mis imágenes se ven realmente extrañas cuando llegan al servidor, así que decidí mirar la matriz de bytes que se enviaba y la que se recibía solo para asegurarme de que era la misma. No es. En el lado de envío de Java, la matriz de bytes contiene números negativos. En el lado de recepción de C #, no hay números negativos.

Los primeros 15 bytes en el lado de recepción (C #)

137 80 78 71 13 10 26 10 0 0 0 13 73 72 68 

Esos mismos bytes pero en el lado de envío (java)

 -119 80 78 71 13 10 26 10 0 0 0 13 73 72 68 

Todos los números no negativos son iguales, y el -119 no es el único número negativo, todos han terminado. Noté que -119 y 137 están separados 256 y me pregunto si eso tiene algo que ver con eso.

El código que estoy usando para leer la imagen (java)

 public static byte[] readPart(String fileName, long offset, int length) throws FileNotFoundException, Exception { byte[] data = new byte[length]; File file = new File(fileName); InputStream is = new FileInputStream(file); is.skip(offset); is.read(data,0,data.length); is.close(); return data; } 

El código que estoy usando para escribir los datos (c #)

  private void writeFile(string fileName, Stream contents) { using (FileStream fs = new FileStream(fileName, FileMode.Append, FileAccess.Write, FileShare.ReadWrite)) { int bufferLen = 65000; byte[] buffer = new byte[bufferLen]; int count = 0; while ((count = contents.Read(buffer, 0, bufferLen)) > 0) { fs.Write(buffer, 0, count); } fs.Close(); } contents.Close(); } 

No sé si eso es algo que siempre sucede y nunca lo había notado antes o si es algo que decidió ir terriblemente mal. Lo que sí sé es que este código funcionó antes para algo muy similar y que no está funcionando ahora.

Si alguien tiene alguna sugerencia o una explicación, realmente lo agradecería.

EDITAR: El motivo por el que mis imágenes parecían extrañas es cómo estaba llamando al método readPart.

 byte[] data = FileUtilities.readPart(fileName,counter,maxFileSize);//counter is the current chunk number 

Cómo debería haber estado llamándolo

 byte[] data = FileUtilities.readPart(fileName,counter*maxFileSize,maxFileSize);//the current chunk * cuhnksize for the offset... 

Gracias a todos, estoy significativamente menos confundido ahora 🙂

Java no tiene bytes sin firmar; todos los bytes se tratan como firmados. Eso es todo.

Todo lo que realmente importa es cómo piensas en los bytes, ya que rara vez necesitas hacer comparaciones en bytes. La única diferencia significativa es que se imprimen como firmados, como ha descubierto.

Si lo desea, puede utilizar, por ejemplo, las utilidades UnsignedBytes de Guava para ver los bytes de Java como sin signo, pero en realidad no hay mucha diferencia práctica.

En Java, el byte es un valor con signo (que usa el complemento de dos para codificar los valores negativos), de modo que lo que ve es correcto si la mayoría de las personas lo ve inesperado.

Para convertir un byte a un valor int sin signo, use b & 0xff

Como explicación adicional, suponga que tiene 137 como un byte sin signo. Eso se representa como:

 1000 1001 

Este valor binario, cuando se expresa como un número de complemento de dos firmado, resulta ser -119 . ( -128 + 9 )

Cualquier valor de bytes sin signo superior a 128 se verá afectado por la diferencia, ya que el esquema de complemento de los dos utiliza de esta forma el bit más a la izquierda.

Tal vez tiene algo que ver con el hecho de que el byte de Java está firmado (rango -128 a 127) mientras que C # no está firmado (0 a 255) :). La información es la misma en binario, simplemente se interpreta de manera diferente.