0

I'm trying to read a .dat using Java with no other Classes. This is the file's structure: Header Serial: Word; //2 bytes Filename: String[255]; //1 byte Date: Word; //2 bytes FieldNumbers: Word; //2 bytes NumbersOfRecords: Word; //2 bytes

Info about Fields 
    FieldCode: Word;   //2 bytes
    FieldName: ShortString;   //1 byte

Info in Field 
    FieldCode: Word;  //2 bytes
    FieldText: String[255];  //1 byte

    DateTime = double

What I must know is how to use BufferedReader to get each Byte, read it as an int, then turn same int to a string and show it on screen. Can I create different Methods for reading each type of data? Can I make it read 2 bytes at the same time?

UPDATE:

    package binarios5;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;

public class Main5 
{

    public static void main(String[] args) throws FileNotFoundException, IOException 
    {

        try 
        {
            Path path = Paths.get("C:\\\\Dev-Pas\\\\EXAMEN2.dat");
            System.out.println("File open");
            byte[] bytes = Files.readAllBytes(path);
            ByteBuffer buffer = ByteBuffer.wrap(bytes);
            buffer.order(ByteOrder.BIG_ENDIAN);
            short serial = buffer.getShort();
            System.out.println("----[CONTENIDO DEL ARCHIVO]--------------------");
            System.out.println("Nro. de Serie: " + serial);
            int largoCadena = buffer.get();//Bytes 1 int Longitud de la cadena
            //System.out.println("largoCadena: " + largoCadena);//33
            byte[] bytesChar = new byte[largoCadena];//CString
            buffer.get(bytesChar);
            String nombre = new String(bytesChar, StandardCharsets.ISO_8859_1);
            System.out.println("Nombre: " + nombre);

            short date = buffer.getShort();//FALTA DECODIFICAR FECHA
            System.out.println("Fecha sin procesar. "+date);//FALTA DECODIFICAR FECHA

            short cantCampos = buffer.getShort(); //cantidad de campos que tienen los registros
            System.out.println("Cantidad de Campos Customizados: "+cantCampos);//debe decir 4
            int[] codCampo = new int[cantCampos];
            String[] nombreCampo = new String[10];


            for (int i = 0; i < cantCampos; i++) //leer RegType segun la cantidad de campos
            {
                codCampo[i] = buffer.getShort();//Bytes 2 codigo del campo
                int largoCadena2 = buffer.get();//Bytes 1 int Longitud de la cadena
                byte[] bytesChar2 = new byte[largoCadena2];
                buffer.get(bytesChar2);
                nombreCampo[i] = new String(bytesChar2, StandardCharsets.ISO_8859_1);
            }

            for (int i = 0; i < cantCampos; i++)//mostrar codigos y campos
            {
                System.out.println("Campo [codigo: " + codCampo[i] + ", descripcion: " + nombreCampo[i] + "]");
            }

            short cantRegistros = buffer.getShort();//cantidad de registros total
            System.out.println("Cantidad de Registros: "+cantRegistros);
            System.out.println("-----------------------");//OK

            String[] contenidoCampo = new String[10];
            for (int i = 0; i < cantRegistros; i++) //leyendo RegData 5 veces
            {
                short cantCamposCompletos = buffer.getShort();

                for (int j = 0; j < cantCamposCompletos; j++)
                {
                    short codCampoInterno = buffer.getShort();
                    int largoCadena3 = buffer.get();
                    byte[] bytesChar3 = new byte[largoCadena3];
                    buffer.get(bytesChar3);
                    contenidoCampo[j] = new String(bytesChar3, StandardCharsets.ISO_8859_1);
                    System.out.println(nombreCampo[j]+": "+contenidoCampo[j]); 
                }
                System.out.println("-----------------------");
            }

            System.out.println("----[FIN CONTENIDO DEL ARCHIVO]-----------------");
        } 
        catch (IOException e)
        {
            System.out.println("File I/O error!");
        }

    }


}
3
  • You read bytes with an InputSTream, not a Reader. A Reader is for characters, not bytes. And all InputStreams have a read() method, returning a byte. docs.oracle.com/javase/8/docs/api/java/io/…. Integer.toString() returns an int (for example 234) into a String, for example "234". Not sure if that's what you mean, though. Could you please give a conrete example, because I don't quire understand how a filename, can both be a String[255] and 1 byte. Commented Aug 13, 2016 at 16:48
  • Reader/Writer are for text not binary. Using Streams for binary. Commented Aug 13, 2016 at 22:56
  • Why byte by byte? This is a job for DataInputStream. NB String[255] is 255 bytes (at least), not one. Commented Aug 20, 2016 at 8:11

2 Answers 2

1

In java Reader and Writer are for Unicode text, String, 2-bytes char.

For binary data, byte[] one needs an InputStream, OutputStream.

One can use an InputStream:

BufferedInputStream in = new BufferedInputStream(new FileInputStream(...));

In your case you want to read short and such. For that you could wrap it around a DataInputStream.

However using a ByteBuffer is easiest to begin with. It can be read from a file (FileChannel), but the simple case is:

Path path = Paths.get("C:/xxx/yyy.dat");
byte[] bytes = Files.readAllBytes(path);
ByteBuffer buffer = ByteBuffer.wrap(bytes);
//buffer.order(ByteOrder.LITTLE_ENDIAN); // So short is read as LSB,MSB

Worked out:

// Header
short serial = buffer.getShort();
byte[] fileNameB = new byte[255];
buffer.get(fileNameB);
// If 0 terminated asciz string:
int len = fileNameB.length;
for (int i = 0; i < fileNameB.length; ++i) {
    if (fileNameB[i] == 0) {
        len = i;
        break;
    }
}
String fileName = new String(fileNameB, 0, len, StandardCharsets.ISO_8859_1);

short date = buffer.getShort();
short fieldNumbers = buffer.getShort();
short numbersOfRecords = buffer.getShort();

for (int fieldI = 0; fieldI < fieldNumber; ++fieldI) {
    // Info about Fields 
    short fieldCode = buffer.getShort();
    //byte fieldName: ShortString;   //1 byte
}

Info in Field FieldCode: Word; //2 bytes FieldText: String[255]; //1 byte

DateTime = double

String getPascalString(ByteBuffer buffer) {
    int length = buffer.get() & 0xFF;
    byte[] bytes = new byte[length];
    buffer.get(bytes);
    return new String(bytes, StandardCharsets.ISO_8859_1);
}

Will deliver: d:/documentos/te...

short packedDate = buffer.getShort();
int year = packedDate & 0x7F; // + 1900?
int month = (packedDate >> 7) & 0xF:
int day = (packedDate >> 11) & 0x1F;
Sign up to request clarification or add additional context in comments.

17 Comments

Are you sure it's ok to use Little Endian? I know the file serial is 14141, but it shows 15671. Edit: just tested: buffer.order(ByteOrder.BIG_ENDIAN); and it gave me 14141. It reads the first line no problem.
@GMP_47 that was my (false) assumption, as the Windows Intel platform in general uses little endian. BIG_ENDIAN is default in java.
Tell me more about that byte[ ]. All bytes are stored in that array and I can just grab each in order and use it as I want?
Yes. Wrapping it in a ByteBuffer allows additional positioning (seek), and reading/writing short/int, instead of juggling with bytes[i] << 8 and such.
It could be: (1) fixed size block, string terminated by \0. (2) variable length field, terminated by \0, (3) Pascal style string: length byte + text bytes (that max length 255 would fit that).
|
0

Readers are meant for reading streams of characters. For reading streams of raw bytes, consider using a InputStream and calling

public int read(byte[] b)

To parse the strings, pass the byte array to the string constructor specifying the encoding (don't use default encoding because it could be utf8 depending of you environment and in your case is not suitable).

https://docs.oracle.com/javase/tutorial/essential/io/index.html

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.