2

Say we have a file like so:

one 
two 
three

(but this file got encrypted)

My crypto method returns the whole file in memory, as a byte[] type.
I know byte arrays don't have a concept of "lines", that's something a Scanner (for example) could have.

I would like to traverse each line, convert it to string and perform my operation on it but I don't know how to:

  1. Find lines in a byte array
  2. Slice the original byte array to "lines" (I would convert those slices to String, to send to my other methods)
  3. Correctly traverse a byte array, where each iteration is a new "line"

Also: do I need to consider the different OS the file might have been composed in? I know that there is some difference between new lines in Windows and Linux and I don't want my method to work only with one format.

Edit: Following some tips from answers here, I was able to write some code that gets the job done. I still wonder if this code is worthy of keeping or I am doing something that can fail in the future:

byte[] decryptedBytes = doMyCrypto(fileName, accessKey);
ByteArrayInputStream byteArrInStrm = new ByteArrayInputStream(decryptedBytes);
InputStreamReader inStrmReader = new InputStreamReader(byteArrInStrm);
BufferedReader buffReader = new BufferedReader(inStrmReader);

String delimRegex = ",";
String line;
String[] values = null;

while ((line = buffReader.readLine()) != null) {
    values = line.split(delimRegex);
    if (Objects.equals(values[0], tableKey)) {
        return values;
    }
}
System.out.println(String.format("No entry with key %s in %s", tableKey, fileName));
return values;

In particular, I was advised to explicitly set the encoding but I was unable to see exactly where?

2
  • Please share what you have written to try and solve this problem. Commented Nov 8, 2019 at 13:36
  • @ScottHunter I realize it may seem like I am not showing enough effort but all I could find about newlines in byte[] (under Java context) is some guy trying to remove newlines and they do it with a mass replace on the whole byte[], which doesn't show me how to slice it. Can I get a tip? Happy to do the legwork, just don't know where to start! Commented Nov 8, 2019 at 13:45

2 Answers 2

7

If you want to stream this, I'd suggest:

  • Create a ByteArrayInputStream to wrap your array
  • Wrap that in an InputStreamReader to convert binary data to text - I suggest you explicitly specify the text encoding being used
  • Create a BufferedReader around that to read a line at a time

Then you can just use:

String line;
while ((line = bufferedReader.readLine()) != null)
{
    // Do something with the line
}

BufferedReader handles line breaks from all operating systems.

So something like this:

byte[] data = ...;
ByteArrayInputStream stream = new ByteArrayInputStream(data);
InputStreamReader streamReader = new InputStreamReader(stream, StandardCharsets.UTF_8);
BufferedReader bufferedReader = new BufferedReader(streamReader);

String line;
while ((line = bufferedReader.readLine()) != null)
{
    System.out.println(line);
}

Note that in general you'd want to use try-with-resources blocks for the streams and readers - but it doesn't matter in this case, because it's just in memory.

Sign up to request clarification or add additional context in comments.

4 Comments

Or use a Scanner, like the OP suggested. In that case, you can use an InputStream directly, i.e. try(Scanner s = new Scanner(new ByteArrayInputStream(array))) { while(s.hasNextLine()) { String line = s.nextLine(); /* Do something with the line */ }
@Holger: Personally I really dislike the Scanner API in a number of ways. I would personally use BufferedReader every time for this.
@JonSkeet, thanks for the tip! I was able to compose something that seems to work but I wonder what is the next step to accept your answer? I wrote some code that I think is in line with what you said but I have doubts. If you think it's good, maybe you can edit your answer by copying it over from my update and then someone else who sees this question can be sure it is the right answer? Sorry that I am confused. I am indeed a little less experienced in SO than you ;)
@DraxDomax: Okay, I'll give a fuller example in my answer.
0

As Scott states i would like to see what you came up with so we can help you alter it to fit your needs.

Regarding your last comment about the OS; if you want to support multiple file types you should consider making several functions that support those different file extensions. As far as i know you do need to specify which file and what type of file you are reading with your code.

3 Comments

I did not mean file types but OS types. File.csv could have been composed in a CRLF editor or an LF editor - I am not sure it matters, maybe java has a method that makes this transparent?
Not sure if this is helpful but java has a Character#isSpace function that determines if the character is 1 of 5 possible spaces, one of them being (new line). Hope this helps!
well I have taken a look and wrote some code accordingly. Not sure it's good enough to post as an answer and accept my own...

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.