I have to read from a text file and format the input. I'm new to java reading from files, and I don't know how to work with just some parts of what I read
Here is the initial file: http://pastebin.com/D0paWtAd
And I have to write in another file the following output:
Average,Joe,44,31,18,12,9,10
I've managed just to take everything from the file and print it to output. I would need help just in taking the output I need and print it to the screen. Any help is appreciated.
This is what I wrote up to now:
public class FileParsing {
public static String
read(String filename) throws IOException {
BufferedReader in = new BufferedReader(new FileReader("C:\\Users\\Bogdi\\Desktop\\example.txt"));
String s;
StringBuilder sb = new StringBuilder();
while((s = in.readLine())!= null) sb.append(s + "\n");
in.close();
return sb.toString();
}
If your goal is to do the specified output in another file you don't need to first get the content of your file in a StringBuilder before processing it, you can append the processed datas directly in a StringBuilder then you can write the result in a file. Here is an example that would work for the given file but you may have to modify it if the keys change in the future:
The following method will correctly process the datas from your file
public static String read(String filename) throws IOException {
BufferedReader in = new BufferedReader(new FileReader(filename));
String s;
StringBuilder sb = new StringBuilder();
while((s = in.readLine())!= null) {
String[] split1 = s.split("=");
if (split1[0].equals("name")) {
StringTokenizer tokenizer = new StringTokenizer(split1[1]);
sb.append(tokenizer.nextToken());
sb.append(",");
sb.append(tokenizer.nextToken());
sb.append(",");
} else if (split1[0].equals("index")) {
sb.append(split1[1] + ",");
} else if (split1[0].equals("FBid")) {
sb.append(split1[1]);
} else {
StringTokenizer tokenizer = new StringTokenizer(split1[1]);
String wasted = tokenizer.nextToken();
sb.append(tokenizer.nextToken() + ",");
}
}
in.close();
return sb.toString();
}
The next method will read any string to a file
public static void writeStringToFile(String string, String filePath) throws IOException {
BufferedWriter writer = new BufferedWriter(
new FileWriter(
new File(filePath)
)
);
writer.write(string);
writer.newLine();
writer.flush();
writer.close();
}
And here is a simple tests (File1.txt contains the datas from the file you shared on paste bin and I write them in another file)
public static void main(String[] args) throws Exception {
String datas = read("C:\\Tests\\File1.txt");
System.out.println(datas);
writeStringToFile(datas, "C:\\Tests\\FileOuput.txt" );
}
It will produce the exact output that you are expecting
[EDIT] #idk, apparently you have an exception executing my example, while it is working fine for me. That could only mean there is an error at data level. Here is the data sample that I used (and I believe I exactly copy the datas you shared)
And here is the result:
Good to know you are using "StringBuilder" component instead being concatenating your String values, way to go :).
More than knowledge on the Java.IO API to work with files, you will need some logic to get the results you expect. Here I came with an approach that could help you, not perfect, but can point you on how to face this problem.
//Reference to your file
String myFilePath = "c:/dev/myFile.txt";
File myFile = new File(myFilePath);
//Create a buffered reader, which is a good start
BufferedReader breader = new BufferedReader(new FileReader(myFile));
//Define this variable called line that will evaluate each line of our file
String line = null;
//I will use a StringBuilder to append the information I need
StringBuilder appender = new StringBuilder();
while ((line = breader.readLine()) != null) {
//First, I will obtain the characters after "equals" sign
String afterEquals = line.substring(line.indexOf("=") + 1, line.length());
//Then, if it contains digits...
if (afterEquals.matches(".*\\d+.*")) {
//I will just get the digits from the line
afterEquals = afterEquals.replaceAll("\\D+","");
}
//Finally, append the contents
appender.append(afterEquals);
appender.append(",");//This is the comma you want to include
}
//I will delete the last comma
appender.deleteCharAt(appender.length() - 1);
//Close the reader...
breader.close();
//Then create a process to write the content
BufferedWriter myWriter = new BufferedWriter(new FileWriter(new File("myResultFile.txt")));
//Write the full contents I get from my appender :)
myWriter.write(appender.toString());
//Close the writer
myWriter.close();
}
Hope this can help you. Happy coding!
Related
I'm really new in Java and I'm trying to figure out how to read a line from .txt file in SD card. The code below doesn't seem to work since it returns an empty result.
public static final String filePath = Environment.getExternalStorageDirectory().getPath();
public static String getProfileInfo() {
String line = "";
StringBuilder sb = new StringBuilder();
try{
File unzippedText = new File(filePath + "profile.txt");
BufferedReader text = new BufferedReader(new FileReader(unzippedText));
sb.append(line);
text.close();
}catch(Exception e){
e.printStackTrace();
}
return sb.toString();
}
Thanks
This code is not going to do anything
sb.append(line);
line is still equal to ""
try reading using the BufferedReader.readLine
line = text.readLine (); // first line only
I have been trying to get a specific columns from a csv file say having 30 columns but i need only 3 columns entirely when i execute the following code only i get only one entire column data..how to get 3 column data at a time.when i run it prints only one column...when i try to print multiple column it shows error message like
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 1
at ReadCVS.main(ReadCVS.java:19)
public static void main(String[] args) throws Exception {
String splitBy = ",";
BufferedReader br = new BufferedReader(new FileReader("txt.csv"));
String line = br.readLine();
while((line = br.readLine()) !=null){
String[] b = line.split(splitBy);
PrintWriter out = new PrintWriter(new FileWriter("new.csv",true));
out.println(b[0]);
out.close();
}
br.close();
}
The problem is probably is:
You have only one line in your, txt.csv file.
When you called br.readLine(); for the first time, that line is read from the file and stored in String line variable. But you ignored that line, and you've read again, in your while condition:
while((line = br.readLine()) !=null)
So maybe you have an empty line or empty string after that first line. Then the while condition is true, but an empty String is stored in line variable. So the b[] has no element and b[0] is out of the bound.
One solution is to change this line:
String line = br.readLine();
to
String line = null;
[EDIT]
So if you try to read a file like the one in mkyong's site (as you linked in your comment) and split the lines by "," and write them in a new file for example, you can use a code like the code below:
public static void main(String[] args) throws IOException {
BufferedWriter out = new BufferedWriter(new FileWriter("c:\\new.csv",true));
BufferedReader br = new BufferedReader(new FileReader("c:\\txt.csv"));
String splitBy = ",";
String line = null;
while((line = br.readLine()) !=null){
StringBuffer newLine = new StringBuffer();
String[] b = line.split(splitBy);
for (int i = 0; i<b.length; i++)
{
if(b[i] == null || b[i].trim().isEmpty())
continue;
newLine.append(b[i].trim() + ";");
}
out.write(newLine.toString());
out.newLine();
}
out.close();
br.close();
}
Also you should know that the following line opens the output file in appendable way(the second boolean parameter in the constructor):
BufferedWriter out = new BufferedWriter(new FileWriter("c:\\new.csv",true));
Also I assumed the contents of the source file is the same as in mkyong's site, somethimg like this:
"1.0.0.0",, , ,"1.0.0.255","16777216", , "16777471","AU" ,, "Australia"
"1.0.1.0" , ,, "1.0.3.255" ,, ,"16777472","16778239" , , "CN" , ,"China"
"1.0.4.0","1.0.7.255","16778240","16779263","AU","Australia"
"1.0.8.0","1.0.15.255","16779264","16781311","CN","China"
"1.0.16.0","1.0.31.255","16781312","16785407","JP","Japan"
"1.0.32.0","1.0.63.255","16785408","16793599","CN","China"
"1.0.64.0","1.0.127.255","16793600","16809983","JP","Japan"
"1.0.128.0","1.0.255.255","16809984","16842751","TH","Thailand"
Good Luck.
I have an object which is serialised and written to a file.
Before de serialising the file back into an object instance, I want to maliciously edit the txt in the file.
//FILE TAMPER
//Lexical block: Tamper
{
String output = null;
//Lexical block make output
{
LinkedList<String> lls = new LinkedList<String>();
//Lexical block: Reader
{
BufferedReader br = new BufferedReader(new FileReader(fileString));
while (br.ready()) {
String readLine = br.readLine();
lls.add(readLine);
}
br.close();
}
//Lexical block: manipulate
{
//Henry Crapper
final String[] llsToArray = lls.toArray(new String[lls.size()]);
for (int i = 0; i < llsToArray.length; i++) {
String line = llsToArray[i];
if (line.contains("Henry")) {
line = line.replace("Henry",
"Fsekc");
llsToArray[i] = line;
}
if (line.contains("Crapper")) {
line = line.replace("Crapper",
"Dhdhfie");
llsToArray[i] = line;
}
lls = new LinkedList<String>(Arrays.asList(llsToArray));
}
}
//Lexical block: write output
{
StringBuilder sb = new StringBuilder();
for (String string : lls) {
sb.append(string).append('\n');
}
output = sb.toString();
}
}
//Lexical block: Writer
{
BufferedWriter bw = new BufferedWriter(new FileWriter(fileString));
bw.write(output);
bw.close();
}
}
However the edited file isn't correct and has some unusual characters.
//Before
¨Ìsr&Snippets.Parsed.EmployeeSerialization0I
bankBalanceLnametLjava/lang/String;xp•Åt
Henry Crappe
//After
ÔøΩÔøΩsr&Snippets.Parsed.EmployeeSerialization0I
bankBalanceLnametLjava/lang/String;xpÔøΩÔøΩt
Fsekc Dhdhfie
I'm guessing there is some sort of non readable character issue or something?
Answer continued in a new question is here
A file which contains a serialized object instance is a binary file: you should not edit it with a BufferedWriter. Edit it with a RandomAccessFile, for example.
If you are wondering of why, the charset used in a Writer could not map one-to-one with a byte. Saving all the file would change also unexpected positions.
I'm calling grep in java to separately count the number of a list of words in a corpus.
BufferedReader fb = new BufferedReader(
new InputStreamReader(
new FileInputStream("french.txt"), "UTF8"));
while ((l = fb.readLine()) != null){
String lpt = "\\b"+l+"\\b";
String[] args = new String[]{"grep","-ic",lpt,corpus};
Process grepCommand = Runtime.getRuntime().exec(args);
grep.waitFor()
}
BufferedReader grepInput = new BufferedReader(new InputStreamReader(grep.getInputStream()));
int tmp = Integer.parseInt(grepInput.readLine());
System.out.println(l+"\t"+tmp);
This works well for my English word-list and corpus. But I also have a French word list and corpus. It doesn't work for french and a sample output on java console looks like this:
� bord 0
� c�t� 0
correct form: "à bord" and "à côté".
Now my question is: where is the problem? Should I fix my java code, or it's a grep issue?
If so how do I fix it. (I also can't see french characters on my terminal correctly even though I changed the encoding to UTF-8).
The problem is in your design. Do not call grep from java. Use pure java implementation instead: read file line by line and implement your own "grep" using pure java API.
But seriously I believe that the problem is in your shell. Did you try to run grep manually and filter French characters? I believe it will not work for you. It depends on your shell configuration and therefore depends on platform. Java can provide platform independent solution. To achieve this you should avoid as much as it is possible using non-pure-java techniques including executing command line utilities.
BTW code that reads line-by-line your file and uses String.contains() or pattern matching for lines filtering even shorter than code that runs grep.
I would suggest that you read the file line by line then call split on the word boundary to get the number of words.
public static void main(String[] args) throws IOException {
final File file = new File("myFile");
try (final BufferedReader bufferedReader =
new BufferedReader(new InputStreamReader(new FileInputStream(file), "UTF-8"))) {
String line;
while ((line = bufferedReader.readLine()) != null) {
final String[] words = line.split("\\b");
System.out.println(words.length + " words in line \"" + line + "\".");
}
}
}
This avoids calling grep from you program.
The odd characters you are getting may well be do to with using the wrong encoding. Are you sure your file is in "UTF-8"?
EDIT
OP wants to read one file line-by-line and then search for occurrences of the read line in another file.
This can still be done more easily using java. Depending on how big your other file is you can either read it into memory first and search it or search it line-by-line also
A simple example reading the file into memory:
public static void main(String[] args) throws UnsupportedEncodingException, IOException {
final File corpusFile = new File("corpus");
final String corpusFileContent = readFileToString(corpusFile);
final File file = new File("myEngramFile");
try (final BufferedReader bufferedReader =
new BufferedReader(new InputStreamReader(new FileInputStream(file), "UTF-8"))) {
String line;
while ((line = bufferedReader.readLine()) != null) {
final int matches = countOccurencesOf(line, corpusFileContent);
};
}
}
private static String readFileToString(final File file) throws IOException {
final StringBuilder stringBuilder = new StringBuilder();
try (final FileChannel fc = new RandomAccessFile(file, "r").getChannel()) {
final ByteBuffer byteBuffer = ByteBuffer.allocate(4096);
final CharsetDecoder charsetDecoder = Charset.forName("UTF-8").newDecoder();
while (fc.read(byteBuffer) > 0) {
byteBuffer.flip();
stringBuilder.append(charsetDecoder.decode(byteBuffer));
byteBuffer.reset();
}
}
return stringBuilder.toString();
}
private static int countOccurencesOf(final String countMatchesOf, final String inString) {
final Matcher matcher = Pattern.compile("\\b" + countMatchesOf + "\\b").matcher(inString);
int count = 0;
while (matcher.find()) {
++count;
}
return count;
}
This should work fine if your "corpus" file is less than a hundred megabytes or so. Any bigger and you will want to change the "countOccurencesOf" method to something like this
private static int countOccurencesOf(final String countMatchesOf, final File inFile) throws IOException {
final Pattern pattern = Pattern.compile("\\b" + countMatchesOf + "\\b");
int count = 0;
try (final BufferedReader bufferedReader =
new BufferedReader(new InputStreamReader(new FileInputStream(inFile), "UTF-8"))) {
String line;
while ((line = bufferedReader.readLine()) != null) {
final Matcher matcher = pattern.matcher(line);
while (matcher.find()) {
++count;
}
};
}
return count;
}
Now you would just pass your "File" object into the method rather than the stringified file.
Note that the streaming approach reads files line-by-line and hence drops the linebreaks, you need to add them back before parsing the String if your Pattern relies on them being there.
I am Writing a java program to remove the comments in the same java program.
I am thinking of using a file reader. But I'm not sure whether it will work.
Because two process will be using the same file.
But I think before executing the code, java file will make a .class file.
So if I use a filereader to edit the java file. It should not give me error that another process is already using this file.
Am I thinking correct?
Thanks in advance.
Yes, you can do that without any problems.
Note: Be careful with things like:
String notAComment = "// This is not a comment";
If you just want to remove comments from a Java program, why don't you do a simple search and replace using a regex, and convert all comments into an empty string?
Here's a verbose way of doing it, in Java:
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.BufferedReader;
class Cleaner{
public static void main( String a[] )
{
String source = readFile("source.java");
System.out.println(source.replaceAll("(?:/\\*(?:[^*]|(?:\\*+[^*/]))*\\*+/)|(?://.*)",""));
}
static String readFile(String fileName) {
File file = new File(fileName);
char[] buffer = null;
try {
BufferedReader bufferedReader = new BufferedReader( new FileReader(file));
buffer = new char[(int)file.length()];
int i = 0;
int c = bufferedReader.read();
while (c != -1) {
buffer[i++] = (char)c;
c = bufferedReader.read();
}
} catch (IOException e) {
e.printStackTrace();
}
return new String(buffer);
}
}
You are right, the are not two processes using the same file, your program will use the .class files and process the .java files. You may want to take a closer look at this page:
Finding Comments in Source Code Using Regular Expressions
Yes, using a FileReader will work. One thing to watch out is the FileEncoding if you might have non-English characters or work across different platforms. In Eclipse and other IDEs you can change the character set for a Java source file to different encodings. If unsure, it might be worth using:
InputStream in = ....
BufferedReader r = new BufferedReader(new InputStreamReader(in, "UTF-8"));
..
and likewise when you are writing the output back out, use an OutputStreamWriter with UTF-8.
Have a look at the post Remove comments from String for doing your stuff. You may use either FileReader or java.util.Scanner class to read the file.
Its late but it may help some to remove all types of comments.
package com.example;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;
class CommentRemover {
public static void main(String a[]) {
File file = new File("F:/Java Examples/Sample.java");
String fileString = readLineByLine(file);
fileString = fileString.replaceAll(
"(?:/\\*(?:[^*]|(?:\\*+[^*/]))*\\*+/)", "");
System.out.println(fileString);
}
private static String readLineByLine(File file) {
String textFile = "";
FileInputStream fstream;
try {
fstream = new FileInputStream(file);
BufferedReader br = new BufferedReader(new InputStreamReader(
fstream));
String strLine;
while ((strLine = br.readLine()) != null) {
textFile = textFile + replaceComments(strLine) + "\n";
}
br.close();
} catch (Exception e) {
e.printStackTrace();
}
return textFile;
}
private static String replaceComments(String strLine) {
if (strLine.startsWith("//")) {
return "";
} else if (strLine.contains("//")) {
if (strLine.contains("\"")) {
int lastIndex = strLine.lastIndexOf("\"");
int lastIndexComment = strLine.lastIndexOf("//");
if (lastIndexComment > lastIndex) { // ( "" // )
strLine = strLine.substring(0, lastIndexComment);
}
} else {
int index = strLine.lastIndexOf("//");
strLine = strLine.substring(0, index);
}
}
return strLine;
}
}
I made a open source library (CommentRemover on GitHub) for this necessity , you can remove single line and multiple line Java Comments.
It supports remove or NOT remove TODO's.
Also it supports JavaScript , HTML , CSS , Properties , JSP and XML Comments too.
Little code snippet how to use it (There is 2 type usage):
First way InternalPath
public static void main(String[] args) throws CommentRemoverException {
// root dir is: /Users/user/Projects/MyProject
// example for startInternalPath
CommentRemover commentRemover = new CommentRemover.CommentRemoverBuilder()
.removeJava(true) // Remove Java file Comments....
.removeJavaScript(true) // Remove JavaScript file Comments....
.removeJSP(true) // etc.. goes like that
.removeTodos(false) // Do Not Touch Todos (leave them alone)
.removeSingleLines(true) // Remove single line type comments
.removeMultiLines(true) // Remove multiple type comments
.startInternalPath("src.main.app") // Starts from {rootDir}/src/main/app , leave it empty string when you want to start from root dir
.setExcludePackages(new String[]{"src.main.java.app.pattern"}) // Refers to {rootDir}/src/main/java/app/pattern and skips this directory
.build();
CommentProcessor commentProcessor = new CommentProcessor(commentRemover);
commentProcessor.start();
}
Second way ExternalPath
public static void main(String[] args) throws CommentRemoverException {
// example for externalInternalPath
CommentRemover commentRemover = new CommentRemover.CommentRemoverBuilder()
.removeJava(true) // Remove Java file Comments....
.removeJavaScript(true) // Remove JavaScript file Comments....
.removeJSP(true) // etc..
.removeTodos(true) // Remove todos
.removeSingleLines(false) // Do not remove single line type comments
.removeMultiLines(true) // Remove multiple type comments
.startExternalPath("/Users/user/Projects/MyOtherProject")// Give it full path for external directories
.setExcludePackages(new String[]{"src.main.java.model"}) // Refers to /Users/user/Projects/MyOtherProject/src/main/java/model and skips this directory.
.build();
CommentProcessor commentProcessor = new CommentProcessor(commentRemover);
commentProcessor.start();
}
public class Copy {
void RemoveComments(String inputFilePath, String outputFilePath) throws FileNotFoundException, IOException {
File in = new File(inputFilePath);
File out = new File(outputFilePath);
BufferedReader bufferedreader = new BufferedReader(new FileReader(in));
PrintWriter pw = new PrintWriter(new FileWriter(out));
String line = null, lineToRemove = null;
while ((line = bufferedreader.readLine()) != null) {
if (line.startsWith("/*") && line.endsWith("*/")) {
lineToRemove = line;
}
if (!line.trim().equals(lineToRemove)) {
pw.println(line);
pw.flush();
}
}
}
}