0

I have built a simple Java program to read data from FRX property files. The issue I am having however, is I need to be able to only read a certain part of the binary from the file. More specifically, I need to begin reading from the file at the value corresponding to a given hex value, and end reading where the ASCII characters stop for that given string of text.

I was capable of doing this in C# using the following program :

using System;
using System.Collections.Generic;
using System.Text;
using System.IO;

    public class GetFromFRX
    {
        public static void Main()
        {
            StringBuilder buffer = new StringBuilder();
            using (BinaryReader b = new BinaryReader(File.Open("frmResidency.frx", FileMode.Open)))
            {
                try
                {
                    b.BaseStream.Seek(641, SeekOrigin.Begin);
                    int length = b.ReadInt32();

                    for (int i = 0; i < length; i++)
                    {
                        buffer.Append(b.ReadChar());
                    }
                }
                catch (Exception e)
                {
                    Console.WriteLine( "Error obtaining resource\n" + e.Message);
                }

            }
            Console.WriteLine(buffer);
        }
    }

And this is my Java program, with which I believe I can just use DataInputStream to do what I need, however I'm unsure of how to use its methods to seek a hex position to start reading bytes and set the length properly. If I run this current code I get no output written in my new text file, where I would expect to just get the output past the first 10 bytes, so I think I don't understand ReadInt() or skipBytes correctly:

  import java.io.*;
  import java.util.*;

  public class Tester3 {
    public static void main(String[] args) throws IOException {

        FileInputStream in = null;
        FileOutputStream out = null;
        DataInputStream din = null;
        DataOutputStream dout = null;

        try {
            in = new FileInputStream("frmResidency.frx");
            din = new DataInputStream(in);
            out = new FileOutputStream("disisworkinlikeacharm.txt");
            dout = new DataOutputStream(out);
            din.skipBytes(10);
            int length = din.readInt();
            int c;

            for(c = 0 ; c < length; c++){
                out.write(c);
            }
        } finally {
            if (in != null) {
                in.close();
            }
            if (out != null) {
                out.close();
            }
            if (dout != null) {
                dout.close();
            }
            if (din != null) {
                din.close();
            }
        }
    }
}

My question is, is there an easy way to implement seeking a certain hex position and reading binary to a length in my code, or should I be using something like RandomAccessFile to accomplish this...

HavelTheGreat
  • 3,299
  • 2
  • 15
  • 34

2 Answers2

1

Well I see one issue: you are writing the index variable of the for loop instead of the next byte from the file. You should at the very least switch out.write(c) to out.write(din.). Do you expect to write the next ten integers or the next 10 bytes? Assuming you want to write the next ten bytes, the following works for me:

import java.io.DataInputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

public class Test {

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

        FileInputStream in = null;
        FileOutputStream out = null;
        try {
            in = new FileInputStream("c:\\tmp\\test.txt");
            DataInputStream din = new DataInputStream(in);
            out = new FileOutputStream("c:\\tmp\\test.out");
            DataOutputStream dout = new DataOutputStream(out);

            din.skipBytes(10);
            int length = din.readInt();
            System.out.println(length);
            int c;

            for (c = 0; c < length; c++) {
                // TODO: first read byte and check for EOF
                out.write(din.read());
            }
        } finally {
            if (in != null) {
                in.close();
            }
            if (out != null) {
                out.close();
            }
        }
    }
}

If you can use Java 7, it is a lot less code to use a try-with-resources loop. This code was for Java 6. I am only closing the File input/output streams since they should be the ones maintaining the file handles. You could close the other streams to be on the safe side of course.

Aaryn Tonita
  • 490
  • 3
  • 7
  • Should I be removing `try`, as it is not using `catch` or `finally`? Also I think you have a few bracket errors in your code. I'm attempting to implement your logic though. – HavelTheGreat Jan 26 '15 at 15:37
  • No, there are no errors. The brackets are part of the try-with-resources. Let me know if you are using Java 6, and I will rewrite the example. – Aaryn Tonita Jan 26 '15 at 15:40
  • Yes, yes sorry I am using Java 6, overlooked that. – HavelTheGreat Jan 26 '15 at 15:41
  • My apologies, I closed the question as I feel that your answer sufficiently answered my initial question, but I have a slight follow up question. If I print out `length` in my program, I get an extremely large negative value. In addition, I am incapable of printing out anything to my text file. If I replace `c < length` with c less than some arbitrary byte number however, I do not have that issue and actually print out bytes. Do you have any idea why this may be happening? – HavelTheGreat Jan 26 '15 at 15:54
  • It has to do with skipBytes, I have identified. Not entirely sure why. – HavelTheGreat Jan 26 '15 at 15:57
  • Well, part of your question confused me in that you said the length was in Hex. Do you mean that the length is indicated by ASCII characters which indicate the length in hexadecimal or that they are raw bytes? What I have written is an integer directly encoded. – Aaryn Tonita Jan 26 '15 at 16:06
  • So basically, I am given a hexadecimal number, say 134, which corresponds to a decimal value indicating the byte position of the beginning of the string I am looking for. I intend on using that decimal value to indicate the start position for reading bytes. – HavelTheGreat Jan 26 '15 at 16:08
  • I created a new question, as I do not feel it is directly related to what you have helped me with: http://stackoverflow.com/questions/28153951/getting-wrong-bytes-from-java-compared-to-c-sharp – HavelTheGreat Jan 26 '15 at 16:09
0

Use din.skipBytes(pos) to move to the required offset in your input.

Neil Masson
  • 2,609
  • 1
  • 15
  • 23
  • You are not reading in anything in your for-loop. You have missed out a call to din.readByte() or some other read function. – Neil Masson Jan 26 '15 at 15:32