I have a file with multiple lines. My java program must read each three lines from it and format them in one row and writes it to another file. How I can tell to ignore some lines in the file?
For example:
File that program reads from:
First,second,third
Blas,Blad,Blaff,
Mop,Mp,Sup
It must turn this three lines to:
First,Sup,Blaff
It does it correct, but how I can tell to program to ignore some lines that have particular words, for example, if it has particular word, like "sub" in one of the lines?
The example of the code is below:
public static void main(String[] args) throws Exception {
String text = "";
String changedText = "";
String first = "", second = "", third = "";
int outerCounter = 0;
int innerCounter = 0;
int arturCounter = 0;
String temp = "";
//first, we read data from file
java.io.File file = new java.io.File("test.txt");
Scanner input = new Scanner(file);
input.useDelimiter("\r");
while(input.hasNextLine()) {
text = input.next();
outerCounter += 1;
innerCounter = 0;
for (String string : text.split(",")) {
innerCounter += 1;
if(outerCounter == 1) {
second = string;
break;
}
else if(outerCounter == 2 && innerCounter == 3) {
third = string;
}
else if(outerCounter == 3 && innerCounter == 3) {
first = string;
outerCounter = 0;
second = second.replace("\n", "").replace("\r", ""); //very important part, solves the problem with new line!
changedText += second + "," + first + "," + third + "\r" + "\n";
}
}
}
//second, we write obtained data to another file
//PrintWriter creates the file
java.io.PrintWriter output = new java.io.PrintWriter("testOutput.txt");
//write formatted output to the file
output.println(changedText);
//close the file
output.close();
System.out.println(changedText);
}
}
Thank you in advance for help.
I would follow the paradigm:
Init an array pos pointer. Say (p) = 0.
Init an array. Say (arr) = []
Create a function to read the next line, name it (a)
Go into a loop.
Call a() to get the next line, say (l) the new line.
Check if EOF
Check (l) for "invalid" words if one found call continue the loop to get the next line
Add the line to (arr)[p] and increment p by one.
If p == 3 write to file (arr)[0] + (arr)[2] + (arr)[1]. Reset (p) = 0.
Else continue;
Related
This question already has an answer here:
What is a StringIndexOutOfBoundsException? How can I fix it?
(1 answer)
Closed 4 years ago.
I'm trying to read in a file that contains a sequence of DNA. And within my program I want to read in each subsequence of that DNA of length 4, and store it in my hashmap to count the occurence of each subsequence. For example if I have the sequence CCACACCACACCCACACACCCAC, and I want every subsequence of length 4, the first 3 subsequences would be:
CCAC, CACA, ACAC, etc.
So in order to do this I have to iterate over the string several times, here is my implementation
try
{
String file = sc.nextLine();
BufferedReader reader = new BufferedReader(new FileReader(file + ".fasta"));
Map<String, Integer> frequency = new HashMap<>();
String line = reader.readLine();
while(line != null)
{
System.out.println("Processing Line: " + line);
String [] kmer = line.split("");
for(String nucleotide : kmer)
{
System.out.print(nucleotide);
int sequence = nucleotide.length();
for(int i = 0; i < sequence; i++)
{
String subsequence = nucleotide.substring(i, i+5);
if(frequency.containsKey(subsequence))
{
frequency.put(subsequence, frequency.get(subsequence) +1);
}
else
{
frequency.put(subsequence, 1);
}
}
}
System.out.println();
line = reader.readLine();
}
System.out.println(frequency);
}
catch(StringIndexOutOfBoundsException e)
{
System.out.println();
}
I have a problem when reaching the end of the string, it won't continue to process due to the error. How would I go about getting around that?
You are calling substring(i, i + 5). At the end of the string i + 5 goes out of bounds. Let's say your string is "ABCDEFGH", length 8, your loop will go from i = 0 to i = 7. When i reaches 4 substring(4, 9) cannot be computed and the exception is raised.
Try this:
for(int i = 0; i < sequence - 4; i++)
You can directly read each line and extract first 4 sub-chars without
the need to splitting it up each time when you read a line.
The error you are getting because when the Program is looping through the splitted characters then it is possible that there are less than 4 characters left altogether at the end to be extracted. Less than 4 chars are responsible which is throwing the error. e.g. suppose you have a line CCACACC then grouping in 4 chars you would get 1st group as complete i.e., CCAC and 2nd group as ACC which is incomplete. So in your code when the line nucleotide.substring(i, i+5); is encountered then probably there is no group of complete 4 characters left at the end that can be extracted and hence the Program throws error. And to extract 4 chars you need to add 4, not 5.
So the work around the code will be to put the extraction line in a try block as given below in the edited code. Replace the loop body with the below code.
while(reader.hasNextLine())
{
line = reader.nextLine();
for(int i = 0; i < line.length; i++)
{
String subsequence = "";
// put the extract operation in a try block
// to avoid crashing
try
{
subsequence = nucleotide.substring(i, i+4);
}
catch(Exception e)
{
// just leave blank to pass the error
}
if(frequency.containsKey(subsequence))
{
frequency.put(subsequence, frequency.get(subsequence) +1);
}
else
{
frequency.put(subsequence, 1);
}
}
Based on the title of your post...try changing the condition for your while loop. Instead of using the current:
String line = reader.readLine();
while(line != null) {
// ...... your code .....
}
use this code:
String line;
while((line = reader.readLine()) != null) {
// If file line is blank then skip to next file line.
if (line.trim().equals("")) {
continue;
}
// ...... your code .....
}
That would cover handling blank file lines.
Now about the StringIndexOutOfBoundsException exception you are experiencing. I believe by now you already basically know why you are receiving this exception and therefore you need to decide what you want to do about it. When a string is to be split into specific length chunks and that length is not equally divisible against the overall length if a specific file line characters then there are obviously a few options available:
Ignore the remaining characters at the end of the file line. Although an easy solution it's not very feasible since it would produce incomplete data. I don't know anything about DNA but I'm certain this would not be the route to take.
Add the remaining DNA sequence (even though it's short) to the Map. Again, I know nothing about DNA and I'm not sure if even this wouldn't be a viable solution. Perhaps it is, I simply don't know.
Add the remaining short DNA sequence to the beginning of the next
incoming file line and carry on breaking that line into 4 character
chunks. Continue doing this until the end of file is reached at which
point if the final DNA sequence is determined to be short then add
that to the Map (or not).
There may of course be other options and whatever they might be it's something you will need to decide. To assist you however, here is code to cover the three options I've mentioned:
Ignore the remaining characters:
Map<String, Integer> frequency = new HashMap<>();
String subsequence;
String line;
try (BufferedReader reader = new BufferedReader(new FileReader("DNA.txt"))) {
while ((line = reader.readLine()) != null) {
// If file line is blank then skip to next file line.
if (line.trim().equals("")) {
continue;
}
for (int i = 0; i < line.length(); i += 4) {
// Get out of loop - Don't want to deal with remaining Chars
if ((i + 4) > (line.length() - 1)) {
break;
}
subsequence = line.substring(i, i + 4);
if (frequency.containsKey(subsequence)) {
frequency.put(subsequence, frequency.get(subsequence) + 1);
}
else {
frequency.put(subsequence, 1);
}
}
}
}
catch (IOException ex) {
ex.printStackTrace();
}
Add the remaining DNA sequence (even though it's short) to the Map:
Map<String, Integer> frequency = new HashMap<>();
String subsequence;
String line;
try (BufferedReader reader = new BufferedReader(new FileReader("DNA.txt"))) {
while ((line = reader.readLine()) != null) {
// If file line is blank then skip to next file line.
if (line.trim().equals("")) {
continue;
}
String lineRemaining = "";
for (int i = 0; i < line.length(); i += 4) {
// Get out of loop - Don't want to deal with remaining Chars
if ((i + 4) > (line.length() - 1)) {
lineRemaining = line.substring(i);
break;
}
subsequence = line.substring(i, i + 4);
if (frequency.containsKey(subsequence)) {
frequency.put(subsequence, frequency.get(subsequence) + 1);
}
else {
frequency.put(subsequence, 1);
}
}
if (lineRemaining.length() > 0) {
subsequence = lineRemaining;
if (frequency.containsKey(subsequence)) {
frequency.put(subsequence, frequency.get(subsequence) + 1);
}
else {
frequency.put(subsequence, 1);
}
}
}
}
catch (IOException ex) {
ex.printStackTrace();
}
Add the remaining short DNA sequence to the beginning of the next incoming file line:
Map<String, Integer> frequency = new HashMap<>();
String lineRemaining = "";
String subsequence;
String line;
try (BufferedReader reader = new BufferedReader(new FileReader("DNA.txt"))) {
while ((line = reader.readLine()) != null) {
// If file line is blank then skip to next file line.
if (line.trim().equals("")) {
continue;
}
// Add remaining portion of last line to new line.
if (lineRemaining.length() > 0) {
line = lineRemaining + line;
lineRemaining = "";
}
for (int i = 0; i < line.length(); i += 4) {
// Get out of loop - Don't want to deal with remaining Chars
if ((i + 4) > (line.length() - 1)) {
lineRemaining = line.substring(i);
break;
}
subsequence = line.substring(i, i + 4);
if (frequency.containsKey(subsequence)) {
frequency.put(subsequence, frequency.get(subsequence) + 1);
}
else {
frequency.put(subsequence, 1);
}
}
}
// If any Chars remaining at end of file then
// add to MAP
if (lineRemaining.length() > 0) {
frequency.put(lineRemaining, 1);
}
}
catch (IOException ex) {
ex.printStackTrace();
}
It is not clear at all from the question description, but I'll guess your input file ends with an empty line.
Try removing the last newline in your input file, or alternatively check against empty in your while loop:
while (line != null && !line.isEmpty())
I work with some big file. I need to check that the file end with a empty line or the previous line end with a LF.
Exemple of file :
a
b
c
d
empty line
To read it I use nio and iterator.
try (Stream<String> ligneFichier = Files.lines(myPath, myCharset)){
Iterator<String> iterator = ligneFichier.iterator();
int i = 0;
while (iterator.hasNext()) {
valeurLigne = iterator.next();
i++;
}
}
When I check the count i I get 4 lines, but there is a 4 + 1 empty (so 5).
Any idea how to heck if the last line end with LF ?
Thanks
If You look for a snippet how to count lines (even with empty lines); here it is:
int result = 0;
try (
FileReader input = new FileReader(filePath);
LineNumberReader count = new LineNumberReader(input);
) { while (count.skip(Long.MAX_VALUE) > 0) {
// Loop just in case the file is > Long.MAX_VALUE or skip() decides to not read the entire file
}
result = count.getLineNumber() + 1; // +1 because line index starts at 0
}
System.out.println(result);
You could use this loop:
int numberOfLines = 0;
while (scanner.hasNextLine()) {
numberOfLines++;
scanner.nextLine();
}
I'm a beginner and need some help. I'm trying to scan a text file into an array line by line, but omitting one line. My text file is
i am
you are
he is
she is
it is
I want to create a method that will scan this and put elements into an array with an exception for one line (that is chosen by entering the String as a parameter for the method). Then erase the original text file and print there the created array (without that one deleted line). Sorry, I suck at explaining.
I have tried this:
public static void deleteLine(String name, String line) throws IOException {
String sc = System.getProperty("user.dir") + new File("").separator;
FileReader fr = new FileReader(sc + name + ".txt");
Scanner scan = new Scanner(fr);
int n = countLines(name); // a well working method returning the number if lines in the file (here 5)
String[] listArray = new String[n-1];
for (int i = 0; i < n-1; i++) {
if (scan.hasNextLine() && !scan.nextLine().equals(line))
listArray[i] = scan.nextLine();
else if (scan.hasNextLine() && scan.nextLine().equals(line))
i--;
else continue;
}
PrintWriter print = new PrintWriter(sc + name + ".txt");
print.write("");
for (int i = 0; i < n-2; i++) {
print.write(listArray[i] + "\n");
}
print.close()
}
I get an error "Line not found" when I enter: deleteLine("all_names","you are") (all_names is the name of the file). I'm sure the problem lies in the for-loop, but I have no idea why this doesn't work. :(
//SOLVED//
This code worked after all. Thanks for answers!
public static void deleteLine(String name, String line) throws IOException{
String sc = System.getProperty("user.dir") + new File("").separator;
FileReader fr = null;
fr = new FileReader(sc+name+".txt");
Scanner scan = new Scanner(fr);
int n = LineCounter(name);
String[] listArray = new String[n-1];
for (int i = 0; i < n-1; i++) {
if (scan.hasNextLine()) {
String nextLine = scan.nextLine();
if (!nextLine.equals(line)) {
listArray[i] = nextLine;
}
else i--;
}
}
PrintWriter print = new PrintWriter(sc+name+".txt");
print.write("");
for(int i=0;i<n-1;i++){
print.write(listArray[i]+System.lineSeparator());
}
print.close();
}
You are reading the lines twice scan.nextLine() while comparing and because of that you run out of the lines.
Replace your loop with this one or similar
for (int i = 0; i < n; i++) {
if (scan.hasNextLine()) {
String nextLine = scan.nextLine();
if (nextLine.equals(line)) {
listArray[i] = nextLine;
}
}
}
Have a look at how you are comparing String objects. You should use the equals method to compare a String's content. Using operators like == and != compares if the String objects are identical.
Now after using equals correctly have a look at how you are using nextLine. Check its Javadoc
I feel LineCounter(name) works because you did not put a ".txt" there. Try removing the ".txt" extension from the file name in the Filereader and Printwriter objects and see if it works. Usually in windows, the extension is not a part of the file name.
Here's an alternative (easier) solution to do what you want, using easier to understand code. (I think)
Also it avoids multiple
loops, but uses a single Java 8 stream to filter instead.
public static void deleteLine(String name, String line) throws IOException {
List<String> lines = Files.readAllLines(Paths.get(name));
lines = lines.stream().filter(v -> !v.equals(line)).collect(Collectors.toList());
System.out.println(lines);
// if you want the String[] - but you don't need it
String[] linesAsStringArr = new String[lines.size()];
linesAsStringArr = lines.toArray(linesAsStringArr);
// write the file using our List<String>
Path out = Paths.get("output.txt"); // or another filename you dynamically create
Files.write(out, lines, Charset.forName("UTF-8"));
}
I am making an app that keeps username and scores from a game in a txt file. The concept is that when it writes a new username and score to the txt file it should open the .txt file, read it and then make a clone of it adding a new uername and score entry in the txt file.
I am thinking of making this with 2 object arrays. The first is the one that is read in and the new will be the one is writen which will have one more entry.
So if player[i] is readen player[i+1] should be writen with new entry.
I am giving u the code below!
private Player[] myplayer=null;
private Player[] mynewplayer=null;
//open Players.txt
int i;
int n;
String filename="players.txt";
try
{
FileReader fp=new FileReader(filename);
BufferedReader bf=new BufferedReader(fp);
n=Integer.parseInt(bf.readLine());
myplayer=new Player[n];
int x=n+1;
mynewplayer=new Player[x];
for(i=0;i<n;i++)
{
String s=bf.readLine();
String user="",score="";
user=s.substring(0,s.indexOf(","));
s=s.substring(s.indexOf(",")+1);
score=s;
myplayer[i]=new Player(user,Double.parseDouble(score));
for(i=0;i<n;i++)
{
mynewplayer[i]= myplayer[i];
}
mynewplayer[x]=new Player(Username,Double.parseDouble(score));
}
bf.close();
fp.close();
}catch(IOException e)
{
System.out.println("Exception was "+e.getMessage());
}
//----------------------------------WRITE mytxt!-------------
n=myplayer.length;
try
{
filename="players.txt";
FileWriter fp=new FileWriter(filename);
fp.write(""+n+"\n");
for(i=0;i<n+1;i++)
fp.write(""+mynewplayer[i]+"\n");
fp.close();
}catch(IOException e)
{
System.out.println("Exception was "+e.getMessage());
}
//----------------------------------WRITE mytxt!-----------
//Get on Message
String s="";
for(i=0;i<mynewplayer.length;i++)
s=s+mynewplayer[i]+"\n";
JOptionPane.showMessageDialog(null,"Players are \n "+s);
Problem is that when it's written, it returns null for mynewplayer.
I suppose the mynewplayer doesnt really take the entries of the "myplayer" but neither writes the new username.
Compile doesnt show any errors. Just writes NULL to the textfile.
Ask me if u want further info on the code writen!
Thanks in advance!
Here is an edited version of your code, with some improvements and there should be a comment around code that I changed, explaining what I did.
Player[] myPlayer = null; // first word uncapitalized, every
Player[] myNewPlayer = null; // other word begins with a capital
//open Players.txt
int i, n; // combine the variables into 1 line
String filename = "players.txt";
try {
FileReader fp = new FileReader(filename);
BufferedReader bf = new BufferedReader(fp);
n = Integer.parseInt(bf.readLine());
// not needed
//myPlayer = new Player[n];
// NOT NEEDED int x = n + 1;
myNewPlayer = new Player[n + 1];
for (i = 0; i < n; i++) {
String s = bf.readLine();
String user, score; // combine variables, doesnt need to initalize them
String[] items = s.split(","); // Splits the line into array elements on every delimiter -> ,
//user = s.substring(0, s.indexOf(","));
//s = s.substring(s.indexOf(",") + 1);
//score = s;
user = items[0];
score = items[1];
// this line below isnt actually needed
//myPlayer[i] = new Player(user, Double.parseDouble(score));
// Create a new player clone, dont copy the previous one
myNewPlayer[i] = new Player(user, Double.parseDouble(score));
}
// We've read all the variables from the text file, now we create the last one
// Since myNewPlayer is (n+1) size, the range of the array is
// 0 to n
// the last index will be n New Score Variable
myNewPlayer[n] = new Player("Username variable", Double.parseDouble("22"));
bf.close();
fp.close();
} catch (IOException e) {
System.out.println("Exception was " + e.getMessage());
}
//----------------------------------WRITE mytxt!-------------
// This is called a ternary operator
// it is a 1 line if statement
// the format is like so
// booleanLogic ? trueAnswer Execution : falseAnswer Execution;
// if () { true }else { false }
n = myNewPlayer != null ? myNewPlayer.length : 0;
// CHANGED HERE - was using the first array rather than second
// dont need the 1st array
try {
filename = "players.txt";
FileWriter fp = new FileWriter(filename);
// Dont need "" before the items
fp.write(n + "\n");
for (i = 0; i < n; i++) {
fp.write(myNewPlayer[i] + "\n");
}
fp.close();
} catch (IOException e) {
System.out.println("Exception was " + e.getMessage());
}
//----------------------------------WRITE mytxt!-----------
//Get on Message
String s = "";
for (i = 0; i < myNewPlayer.length; i++) {
// s += ""; is like doing s = s + "";
s += myNewPlayer[i] + "\n";
}
JOptionPane.showMessageDialog(null, "Players are \n " + s);
I believe that your problem is this:
for(i=0;i<n;i++)
{
String s=bf.readLine();
String user="",score="";
user=s.substring(0,s.indexOf(","));
s=s.substring(s.indexOf(",")+1);
score=s;
myplayer[i]=new Player(user,Double.parseDouble(score));
for(i=0;i<n;i++)
{
mynewplayer[i]= myplayer[i];
}
mynewplayer[x]=new Player(Username,Double.parseDouble(score));
}
You have nested loops, which is fine, but they use the same counter (the variable i ).
So what is happening is the first line of the file is read, and then added to myplayer[0]. However, instead of just also adding it to mynewplayer[0], you start another loop on i. This loop:
for(i=0;i<n;i++)
{
mynewplayer[i]= myplayer[i];
}
is going to copy the first player into mynewplayer[0]...and then null into every other entry (since myplayer only has the firsdt element filled.
The problem is that after that loop completes, i will equal n, so when you get back to the top of the outer loop, the check $i
Perhaps what you should do is this:
for(i=0;i<n;i++)
{
String s=bf.readLine();
String user="",score="";
user=s.substring(0,s.indexOf(","));
s=s.substring(s.indexOf(",")+1);
score=s;
myplayer[i]=new Player(user,Double.parseDouble(score));
mynewplayer[i]= new Player(user,Double.parseDouble(score));
}
mynewplayer[x]=new Player(<the new username>,Double.parseDouble(<the new score>));
So my program reads in a file and displays it just fine, but when I reverse it, it only displays on one single line.
import java.io.*;
public class palinPractice
{
public static void main(String args[]) throws IOException
{
BufferedReader br = new BufferedReader(new FileReader("data.txt"));
PrintWriter pr = new PrintWriter(new FileWriter("JCdata.txt"));
String rec;
String temp = "";
while((rec = br.readLine()) != null) // Reads Through
{
System.out.println(rec);
/*for(int i = rec.length()-1;i>=0;i--) // Reverse
{
temp = temp + rec.charAt(i);
}*/
}
System.out.println(temp);
I commented out the reverse statement, but there it is. When I read in the file and display it, it works and it has spaces and new lines where they are supposed to be, but when reversed it displays on one long single line.
Any help would be appreciated.
Your System.out.println(rec) is in a while loop, and rec is being reassigned to br.readLine(). Each time you read a new line, the first thing you do is print that out.
Meanwhile, if you uncomment your reverse stuff, you're building temp into a big reversed string of the entire document and waiting until you end the while loop to print anything.
There are two possible solutions, depending on what you intend to do with this.
If you don't need to keep the total reverse value, you can print each reversed line one at a time. Change the body of your while loop to look like this:
while((rec = br.readLine()) != null) {
System.out.println(rec);
temp = "";
for(int i = rec.length()-1;i>=0;--i) {
temp = temp + rec.charAt(i);
}
System.out.println(temp);
}
The second option is to just build up one big string and print it all in one shot at the end. If you want to do this though, you'll have to append in some '\n' characters.
So, right after your for loop that reverses the line, as the last line of your while loop, add this line:
temp = temp + System.getProperty("line.separator");
Now after reading each line and reversing it, you add a line break into the string before reading the next line. When you finish and exit the while loop, a single System.out.println will take care of it all.
That'd look like this:
while((rec = br.readLine()) != null) {
System.out.println(rec);
for(int i = rec.length()-1; i>=0; --i) {
temp = temp + rec.charAt(i);
}
temp = temp + System.getProperty("line.separator");
}
System.out.println(temp);
Try
while((rec = br.readLine()) != null) // Reads Through
{
System.out.println(rec);
for(int i = rec.length()-1;i>=0;i--) // Reverse
{
temp = temp + rec.charAt(i);
}
temp = temp + System.getProperty("line.separator");
}