Scanner unable to read foreign characters in file - java

I'm currently creating a tool that can extract and search for data stored on a smartwatch for a University project.
I have been able to extract a file in particular called "Node.db" from my smartwatch which contains the Bluetooth MAC Address of the mobile phone the smartwatch is connected to. I am now trying to create a scanner than will scan this "node.db" file and print out the MAC Address.
This is the code I currently have:
// Identify the location of the node.txt file
File file = new File("C:\\WatchData\\node.txt");
// Notify the user that Bluetooth extraction has initalized
Txt_Results.append("Pulling bluetooth data...");
Scanner in = null;
try {
in = new Scanner(file);
while(in.hasNext())
{ // Scan till the end of the file
String line=in.nextLine();
// Scan the file for this string
if(line.contains("settings.bluetooth"))
// Print the MAC Address string out for the user
System.out.println(line);
}
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
A previous function converted the file to .txt.
The code searches each line and looks for "settings.bluetooth" and should print out this line which contains the MAC Address if it is found. However, I believe the format of the node.db file is stopping the scanner from finding this string. I believe that some of the data in the file is encoded. An example of how the data is presented is shown below. I believe it is the black characters it doesn't recognize:
When I run the code on the file, the program will simply hang and provide no error message. I have left the program to run for over 20 minutes and still no success.
The exact line I am trying to print out from the file is shown below:
I have tested this code on a text file without these encoded characters and can conclude that the code does work. So my question is the following:
Is there a way that I can get the scanner to skip the characters it doesn't recognize in the file so it can continue scanning the file?
Thanks in advance.

Since you didn't provide the files here, so I can't write code to test on your files. It looks like your files have an different encoding than that Java uses to decode it.
So, you need to try different encoding settings for your input stream.
Usually, you specify the encoding by:
String encoding = "UTF-8"; // try "UTF-8" first and also change to other encodings to see the results
Reader reader = new InputStreamReader(new FileInputStream("your_file_name"), encoding);
Refer to this post for more information. This post also talks about how to write code to detect the encoding of your file.
BTW, the decoded characters shown in your file with a dark background are some control characters in ASCII.
I would also suggest you try changing the decoding method of your text viewer application to see if you can actually make the text display correctly in a particular encoding method.
UPDATE
It looks like Scanner doesn't work while using other IO class actually works fine.
StringBuilder sb = new StringBuilder();
try (BufferedReader reader = new BufferedReader(new FileReader("node.txt"))) {
String line;
while ((line = reader.readLine()) != null) {
sb.append(line);
}
} catch (Exception e) {
// TODO: handle exception
}
int index = sb.indexOf("settings.bluetooth");
if (index != -1)
System.out.println(sb.substring(index, index + 18));
UPDATE
It looks like only when you create a Scanner from a File will cause an exception in one of the Scanner's inner method when reading from the file. But using an input stream as below will always work, even wrapping it inside a Scanner.
try (Scanner s = new Scanner(new FileInputStream("node.txt"))) {
while(s.hasNext()) {
System.out.println(s.next());
}
} catch (Exception e) {
e.printStackTrace();
}
UPDATE
This solution just eliminates all the illegal characters from your file.
public static void main(String args[]) {
String encoding = "UTF-8"; // try "UTF-8" first and also change to other encodings to see the results
StringBuilder sb = new StringBuilder();
try(Reader reader = new InputStreamReader(new FileInputStream("node.txt"), encoding)) {
int c = -1;
while ((c = reader.read()) != -1) {
if (eligible(c)) {
sb.append((char)c);
}
}
} catch (Exception e){
e.printStackTrace();
}
int index = sb.indexOf("settings.bluetooth");
if (index >= 0) {
System.out.println(sb.substring(index));
}
}
public static boolean eligible(int c) {
return (c >= 'a' && c <= 'z' || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || c == '.');
}

Related

Find a string (or a line) in a txt File Java

let's say I have a txt file containing:
john
dani
zack
the user will input a string, for example "omar"
I want the program to search that txt file for the String "omar", if it doesn't exist, simply display "doesn't exist".
I tried the function String.endsWith() or String.startsWith(), but that of course displays "doesn't exist" 3 times.
I started java only 3 weeks ago, so I am a total newbie...please bear with me.
thank you.
Just read this text file and put each word in to a List and you can check whether that List contains your word.
You can use Scanner scanner=new Scanner("FileNameWithPath"); to read file and you can try following to add words to List.
List<String> list=new ArrayList<>();
while(scanner.hasNextLine()){
list.add(scanner.nextLine());
}
Then check your word is there or not
if(list.contains("yourWord")){
// found.
}else{
// not found
}
BTW you can search directly in file too.
while(scanner.hasNextLine()){
if("yourWord".equals(scanner.nextLine().trim())){
// found
break;
}else{
// not found
}
}
use String.contains(your search String) instead of String.endsWith() or String.startsWith()
eg
str.contains("omar");
You can go other way around. Instead of printing 'does not exist', print 'exists' if match is found while traversing the file and break; If entire file is traversed and no match was found, only then go ahead and display 'does not exist'.
Also, use String.contains() in place of str.startsWith() or str.endsWith(). Contains check will search for a match in the entire string and not just at the start or end.
Hope it makes sense.
Read the content of the text file: http://www.javapractices.com/topic/TopicAction.do?Id=42
And after that just use the textData.contains(user_input); method, where textData is the data read from the file, and the user_input is the string that is searched by the user
UPDATE
public static StringBuilder readFile(String path)
{
// Assumes that a file article.rss is available on the SD card
File file = new File(path);
StringBuilder builder = new StringBuilder();
if (!file.exists()) {
throw new RuntimeException("File not found");
}
BufferedReader reader = null;
try {
reader = new BufferedReader(new FileReader(file));
String line;
while ((line = reader.readLine()) != null) {
builder.append(line);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (reader != null) {
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return builder;
}
This method returns the StringBuilder created from the data you have read from the text file given as parameter.
You can see if the user input string is in the file like this:
int index = readFile(filePath).indexOf(user_input);
if ( index > -1 )
System.out.println("exists");
You can do this with Files.lines:
try(Stream<String> lines = Files.lines(Paths.get("...")) ) {
if(lines.anyMatch("omar"::equals)) {
//or lines.anyMatch(l -> l.contains("omar"))
System.out.println("found");
} else {
System.out.println("not found");
}
}
Note that it uses the UTF-8 charset to read the file, if that's not what you want you can pass your charset as the second argument to Files.lines.

Reading from InflaterInputStream and parsing the result

I am quite new to java, just started yesterday. Since I am a big fan of learning by doing, I am making a small project with it. But I am stucked in this part. I have written a file using this function:
public static boolean writeZippedFile(File destFile, byte[] input) {
try {
// create file if doesn't exist part was here
try (OutputStream out = new DeflaterOutputStream(new FileOutputStream(destFile))) {
out.write(input);
}
return true;
} catch (IOException e) {
// error handlind was here
}
}
Now that I have successully wrote a compressed file using above method, I want to read it back to console. First I need to be able to read the decompressed content and write string representaion of that content to console. However, I have a second problem that I don't want to write characters up to first \0 null character. Here is how I attempt to read the compressed file:
try (InputStream is = new InflaterInputStream(new FileInputStream(destFile))) {
}
and I am completely stuck here. Question is, how to discard first few character until '\0' and then write the rest of the decompressed file to console.
I understand that your data contain text since you want to print a string respresentation. I further assume that the text contains unicode characters. If this is true, then your console should also support unicode for the characters to be displayed correctly.
So you should first read the data byte by byte until you encounter the \0 character and then you can use a BufferedReader to print the rest of the data as lines of text.
try (InputStream is = new InflaterInputStream(new FileInputStream(destFile))) {
// read the stream a single byte each time until we encounter '\0'
int aByte = 0;
while ((aByte = is.read()) != -1) {
if (aByte == '\0') {
break;
}
}
// from now on we want to print the data
BufferedReader b = new BufferedReader(new InputStreamReader(is, "UTF8"));
String line = null;
while ((line = b.readLine()) != null) {
System.out.println(line);
}
b.close();
} catch(IOException e) { // handle }
Skip the first few characters using InputStream#read()
while (is.read() != '\0');

How do I quadruple the integer values in a text file? [closed]

This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center.
Closed 9 years ago.
I guess this comes down to reading and writing to the same file. I would like to be able to return the same text file as is input, but with all integer values quadrupled. Should I even be attempting this with Java, or is it better to write to a new file and overwrite the original .txt file?
In essence, I'm trying to transform This:
12
fish
55 10 yellow 3
into this:
48
fish
220 40 yellow 12
Here's what I've got so far. Currently, it doesn't modify the .txt file.
import java.io.*;
import java.util.Scanner;
public class CharacterStretcher
{
public static void main(String[] args)
{
Scanner keyboard = new Scanner( System.in );
System.out.println("Copy and paste the path of the file to fix");
// get which file you want to read and write
File file = new File(keyboard.next());
File file2 = new File("temp.txt");
BufferedReader reader;
BufferedWriter writer;
try {
// new a writer and point the writer to the file
FileInputStream fstream = new FileInputStream(file);
// Use DataInputStream to read binary NOT text.
reader = new BufferedReader(new InputStreamReader(fstream));
writer = new BufferedWriter(new FileWriter(file2, true));
String line = "";
String temp = "";
int var = 0;
int start = 0;
System.out.println("000");
while ((line = reader.readLine()) != null)
{
System.out.println("a");
if(line.contains("="))
{
System.out.println("b");
var = 0;
temp = line.substring(line.indexOf('='));
for(int x = 0; x < temp.length(); x++)
{
System.out.println(temp.charAt(x));
if(temp.charAt(x)>47 && temp.charAt(x)<58) //if 0<=char<=9
{
if(start==0)
start = x;
var*=10;
var+=temp.indexOf(x)-48; //converts back into single digit
}
else
{
if(start!=0)
{
temp = temp.substring(0, start) + var*4 + temp.substring(x);
//writer.write(line.substring(0, line.indexOf('=')) + temp);
//TODO: Currently writes a bunch of garbage to the end of the file, how to write in the middle?
//move x if var*4 has an extra digit
if((var<10 && var>2)
|| (var<100 && var>24)
|| (var<1000 && var>249)
|| (var<10000 && var>2499))
x++;
}
//start = 0;
}
System.out.println(temp + " " + start);
}
if(start==0)
writer.write(line);
else
writer.write(temp);
}
}
System.out.println("end");
// writer the content to the file
//writer.write("I write something to a file.");
// always remember to close the writer
writer.close();
//writer = null;
file2.renameTo(file); //TODO: Not sure if this works...
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
Given that this is a pretty quick and simple hack of a formatted text file, I don't think you need to be too clever about it.
Your logic for deciding whether you are looking at a number is pretty complex and I'd say it's overkill.
I've written up a basic outline of what I'd do in this instance.
It's not very clever or impressive, but should get the job done I think.
I've left out the overwriting and reading the input form the console so you get to do some of the implementation yourself ;-)
import java.io.*;
public class CharacterStretcher {
public static void main(String[] args) {
//Assumes the input is at c:\data.txt
File inputFile = new File("c:\\data.txt");
//Assumes the output is at c:\temp.txt
File outputFile = new File("c:\\temp.txt");
try {
//Construct a file reader and writer
final FileInputStream fstream = new FileInputStream(inputFile);
final BufferedReader reader = new BufferedReader(new InputStreamReader(fstream));
final BufferedWriter writer = new BufferedWriter(new FileWriter(outputFile, false));
//Read the file line by line...
String line;
while ((line = reader.readLine()) != null) {
//Create a StringBuilder to build our modified lines that will
//go into the output file
StringBuilder newLine = new StringBuilder();
//Split each line from the input file by spaces
String[] parts = line.split(" ");
//For each part of the input line, check if it's a number
for (String part : parts) {
try {
//If we can parse the part as an integer, we assume
//it's a number because it almost certainly is!
int number = Integer.parseInt(part);
//We add this to out new line, but multiply it by 4
newLine.append(String.valueOf(number * 4));
} catch (NumberFormatException nfEx) {
//If we couldn't parse it as an integer, we just add it
//to the new line - it's going to be a String.
newLine.append(part);
}
//Add a space between each part on the new line
newLine.append(" ");
}
//Write the new line to the output file remembering to chop the
//trailing space off the end, and remembering to add the line
//breaks
writer.append(newLine.toString().substring(0, newLine.toString().length() - 1) + "\r\n");
writer.flush();
}
//Close the file handles.
reader.close();
writer.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
You may want to consider one of these:
Build the new file in memory, rather than trying to write to the same file you are reading from. You could use StringBuilder for this.
Write to a new file, then overwrite the old file with the new one. This SO Question may help you there.
With both of these, you will be able to see your whole output, separate from the input file.
Additionally, with option (2), you don't have the risk of the operation failing in the middle and giving you a messed up file.
Now, you certainly can modify the file in-place. But it seems like unnecessary complexity for your case, unless you have really huge input files.
At the very least, if you try it this way first, you can narrow down on why the more complicated version is failing.
You cannot read and simultaneously write to the same file, because this would modify the text you currently read. This means, you must first write a modified new file and later rename it to the original one. You probably need to remove the original file before renameing.
For renaming, you can use File.renameTo or see one of the many SO's questions
You seem to parse integers in your code by collecting single digits and adding them up. You should consider using either a Scanner.nextInt or employ Integer.parseInt.
You can read your file line by line, split the words at white space and then parse them and check if it is either an integer or some other word.

BufferedReader not reading file (Android)

I am having a problem reading files with bufferedReader... I am trying to read in a dictionary file where every word is on a newline. It works for one file I have, but when I tried adding a larger wordlist file the enable wordlist and then on the first read: 'while ((currentLine=br.readLine()) != null) ' it cause an exception with no description... Please help!
try
{
InputStream is = this.getResources().openRawResource(R.raw.enable1);
BufferedReader br = new BufferedReader(new InputStreamReader(is));
String currentLine=null;
while ((currentLine=br.readLine()) != null)
{
dictionaryList.add(currentLine);
}
br.close();
}
catch (Exception e)
{
//error here
}
*Looks like there is a file size limit of 1048576 bytes... otherwise it crashes.
So I like I said in the edit the new wordlist was over 1048576 bytes and was causing an IO exception without any error... (i had a string set to e.Message() in the catch put the message was null)
What I did was divide the wordlist into separate files based on word size (btw there are 26 different files! message me if you want them)
then depending on the size of the word I have I load the specific wordlist where all of the files are in the format enable# (# is the word size). If anyone wants to know I am doing that like this:
int wordListID=0;
String wordList="enable"+goodText.length();
try {
Class res = R.raw.class;
Field field = res.getField(wordList);
wordListID= field.getInt(null);
}
catch (Exception e) {
//something
}
i then send that specific wordListID to:
InputStream is = this.getResources().openRawResource(wordListID);
and know I have a small enough file which actually helps my performance too!
*This is my first application so I may not be doing things the correct way... just trying to get the hang of things

How can I recognize a special delimiter string when reading from a file of strings?

I want to read strings from a file. When a certain string (><) is found, I want to start reading integers instead, and convert them to binary strings.
My program is reading the strings in and saving them in an ArrayList successfully, but
it does not recognise the >< symbol and therefore the reading of the binary strings is not successful.
The Code
try {
FileInputStream fstream = new FileInputStream(fc.getSelectedFile().getPath());
// Get the object of DataInputStream
DataInputStream ino = new DataInputStream(fstream);
BufferedReader br = new BufferedReader(new InputStreamReader(ino));
String ln;
String str, next;
int line, c =0;
while ((ln = br.readLine()) != null) {
character = ln;
System.out.println(character);
iname.add(ln); // arraylist that holds the strings
if (iname.get(c).equals("><")) {
break; // break and moves
// on with the following while loop to start reading binary strings instead.
}
c++;
}
String s = "";
// System.out.println("SEQUENCE of bytes");
while ((line = ino.read()) != -1) {
String temp = Integer.toString(line, 2);
arrayl.add(temp);
System.out.println("telise? oxii");
System.out.println(line);
}
ino.close();
} catch (Exception exc) { }
The file I'm trying to read is for example:
T
E
a
v
X
L
A
.
x
"><"
sequence of bytes.
Where the last part is saved as bytes and in the textfile appears like that. no worries this bit works. all the strings are saved in a new line.
< is two characters and iname.get(c) is only one character.
What u should do is test if ln equals > and then another test if the next character equals < . If both test pass then break out of the loop.
you will have to becarefull
Use a Scanner. It allows you to specify a delimiter, and has methods for reading input tokens as String or int.
Could you not do something like:
while ((ln = br.readLine()) != null){
character=ln;
System.out.println(character);
//
// Look for magic characters >< and stop reading if found
//
if (character.indexOf("><") >= 0) {
break;
}
iname.add(ln);
}
This would work if you didn't want to add the magic symbol to your ArrayList. Your code sample is incomplete - if you're still having trouble you'd need to post the whole class.

Categories

Resources