How to add line numbers to a text file? - java

So I need to make a program that reads a file containing text and then adds line numbers to each line. What I have so far prints out the line number but instead of just printing out each line, it prints all of the text in each line. How can I just have it so it prints out the line?
Here's the code I have so far:
public static void main(String[] args) throws FileNotFoundException {
try {
ArrayList<String> poem = readPoem("src\\P7_2\\input.txt");
number("output.txt",poem);
}catch(Exception e){
System.out.println("File not found.");
}
}
public static ArrayList<String> readPoem(String filename) throws FileNotFoundException {
ArrayList<String> lineList = new ArrayList<String>();
Scanner in = new Scanner(new File(filename));
while (in.hasNextLine()) {
lineList.add(in.nextLine());
}
in.close();
return lineList;
}
public static void number (String filename,ArrayList<String> lines) throws FileNotFoundException{
PrintWriter out = new PrintWriter(filename);
for(int i = 0; i<lines.size(); i++){
out.println("/* " + i + "*/" + lines);
}
out.close();
}

Here is a shorter version of your program using new capabilities offered by Java 7; it supposes that you have a short enough source file:
final Charset charset = StandardCharsets.UTF_8;
final String lineSeparator = System.lineSeparator();
final Path src = Paths.get("src\\P7_2\\input.txt");
final Path dst = Paths.get("output.txt");
try (
final BufferedWriter writer = Files.newBufferedWriter(src, charset, StandardOpenOption.CREATE);
) {
int lineNumber = 1;
for (final String line: Files.readAllLines(src, charset))
writer.write(String.format("/* %d */ %s%s", lineNumber++, line, lineSeparator));
writer.flush();
}

Use
out.println("/* " + i + "*/" + lines.get(i));
in place of
out.println("/* " + i + "*/" + lines);
You are printing complete list in each line.

i'd say this is your problem:
out.println("/* " + i + "*/" + lines);
//this prints all the lines each loop execution
you can try using:
int i = 1; //or the first value you wish
for(String a : lines){
out.println("/* " + i + "*/" + a);
i++;
}

Related

"Exception: Scanner closed" how to re-open it within (while.. loop)

I am new to coding and trying to learn JAVA and with different approaches for simple tasks.
I want to make a simple address Book with functions like "Add contact, search by number, search by name etc." Most of my methods work but I have a problem with the following two.
When I call modify Contact even if I tried to replace the name ,the code creates a new line in the file. So then I call delete By Name to delete the unmodified line, and I am getting the following error.(I know the cause of the error but I cannot find a solution that works....)
public static void modifyContact(String namee){
Scanner sca =new Scanner(System.in);
String newName = sca.nextLine();
try {
String[] s;
boolean foundPerson = false;
Scanner sc = new Scanner(new File("addressBook.txt"));
while (sc.hasNextLine()) {
s = sc.nextLine().split(",");
if (s[0].equals(namee)) {
s[0]=s[0].replace(s[0],newName);
System.out.println("Name is " + namee + " phone number is " + s[1] + " ,address is " + s[3] + " and email is " + s[2]);
foundPerson = true;
deleteByName(namee);
File file =new File("addressBook.txt");
FileWriter pw = new FileWriter(file,true);
pw.write(s[0]+","+s[1]+","+s[2]+","+s[3]);
pw.close();
}
}
sc.close();
deleteByName(namee);
if (!foundPerson) {
System.out.println("No contact found with " + namee);
}
}
catch (IOException ex) {
//System.out.println(ex.getMessage());
}
}
public static void deleteByName(String na){
try{
File inputFile = new File("addressBook.txt"); // Your file
File tempFile = new File("TempFile.txt");// temp file
BufferedReader reader = new BufferedReader(new FileReader(inputFile));
BufferedWriter writer = new BufferedWriter(new FileWriter(tempFile));
String currentLine;
while((currentLine = reader.readLine()) != null) {
if(currentLine.contains(na))
continue;
writer.write(currentLine);
writer.newLine();
}
writer.close();
reader.close();
boolean del=inputFile.delete();
boolean successful = tempFile.renameTo(inputFile);
System.out.println(del);
System.out.println(successful);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
Exception in thread "main" java.lang.IllegalStateException: Scanner closed
at java.base/java.util.Scanner.ensureOpen(Scanner.java:1150)
at java.base/java.util.Scanner.findWithinHorizon(Scanner.java:1781)
at java.base/java.util.Scanner.hasNextLine(Scanner.java:1610)
at com.christos.hw.Main.modifyContact(Main.java:170)
at com.christos.hw.Main.displayMenu(Main.java:268)
at com.christos.hw.Main.selectAgain(Main.java:96)
at com.christos.hw.Main.displayMenu(Main.java:231)
at com.christos.hw.Main.main(Main.java:12)
There are two solutions:
Don't close the scanner. Keep it open until you don't need it. In other words, close it after the loop.
Recreate the scanner by calling sc = new Scanner(new File("addressBook.txt"));. However, since this will create a new scanner, it'll start reading from the first line again.
You should call sc.close(); after the while loop, not inside it. With your logic, the scanner is unusable from second iteration of the loop itself.
The problem is when you close a scanner with system.in the input stream from system is also closed. so you will not be able to reuse the scanner even if you create a new scanner with System.in .If you are using java 7 you can use try with resources to close all the autocCleasable resources by Java itself. This will resolve the issue.
public static void modifyContact(String namee) {
File file = new File("addressBook.txt");
try (Scanner sca = new Scanner(System.in);
Scanner sc = new Scanner(file);
FileWriter pw = new FileWriter(file, true);) {
String[] s;
boolean foundPerson = false;
String newName = sca.nextLine();
while (sc.hasNextLine()) {
s = sc.nextLine().split(",");
if (s[0].equals(namee)) {
s[0] = s[0].replace(s[0], newName);
System.out.println("Name is " + namee + " phone number is " + s[1] + " ,address is " + s[3]
+ " and email is " + s[2]);
foundPerson = true;
deleteByName(namee);
pw.write(s[0] + "," + s[1] + "," + s[2] + "," + s[3]);
}
}
if (!foundPerson) {
System.out.println("No contact found with " + namee);
}
} catch (IOException ex) {
// System.out.println(ex.getMessage());
}
}
I added after the loop
sc.close();
deleteByName(namee);
and it seems to works fine.
Thank you all for the help.
Your main problem is that you call deleteByName() where you remove original file inside the loop and then reuse Scanner.
You should do it like this:
Find all name
Call deleteByName() with all found names.
public final class AddressBookManager {
private final File file;
public AddressBookManager(File file) {
this.file = file;
}
public void modifyContact(String oldName, String newName) throws IOException {
if (isContactExists(oldName))
updateContactName(oldName, newName);
}
private boolean isContactExists(String name) throws FileNotFoundException {
try (Scanner scan = new Scanner(file)) {
while (scan.hasNextLine()) {
String str = scan.nextLine();
if (str.startsWith(name + ',')) {
String[] parts = str.split(",");
System.out.format("Contact found. Name '%s', phone number '%s', address '%s', email '%s'\n", parts[0], parts[1], parts[2],
parts[3]);
return true;
}
}
System.out.println("No contact found with name '" + name + '\'');
return false;
}
}
private void updateContactName(String curName, String newName) throws IOException {
File tmp = new File(file.getParent(), "TempFile.txt");
try (BufferedReader in = new BufferedReader(new FileReader(file));
BufferedWriter out = new BufferedWriter(new FileWriter(tmp))) {
String str;
while ((str = in.readLine()) != null) {
if (str.startsWith(curName))
str = newName + str.substring(str.indexOf(','));
out.write(str);
out.newLine();
}
}
System.out.println("remove old file: " + file.delete());
System.out.println("rename temp file: " + tmp.renameTo(file));
}
public static void main(String... args) throws IOException {
AddressBookManager addressBookManager = new AddressBookManager(new File("d:/addressBook.txt"));
String curName = "oleg";
String newName = getNewName(curName);
addressBookManager.modifyContact(curName, newName);
}
private static String getNewName(String curName) {
try (Scanner scan = new Scanner(System.in)) {
System.out.print("Enter new name for (" + curName + "): ");
return scan.nextLine();
}
}
}

Java: I am unable to print to a text file in a while loop, despite being able to do so before the while loop

I need to print out a bunch of strings to a file, but I seem to be making some mistake. There is no error message and if I put normal print statements inside the while loop; it prints those. It just does not print it to the file. A different part of the program reads another file, and gives a line to this program to write into a file.
Code:
public static void writeToFile (String a, String username) throws FileNotFoundException {
Scanner lineScan = new Scanner (a);
String name = lineScan.next();
PrintStream newFile = new PrintStream (new File (username+".txt"));
//The below newFile command works
newFile.println(username);
if ((username.toUpperCase()).equals(name.toUpperCase()))
{
int count = 0;
while (lineScan.hasNextInt())
{
int pop = lineScan.nextInt();
String s1 = 1920 + (10*count) + ": " + pop;
newFile.println(s1);
count++;
}
newFile.close();
}
}
You can try this:
public static void writeToFile (String a, String username) throws FileNotFoundException {
Scanner lineScan = new Scanner (a);
String name = lineScan.next();
PrintStream newFile = new PrintStream (new File (username+".txt"));
//The below newFile command works
newFile.println(username);
if ((username.toUpperCase()).equals(name.toUpperCase()))
{
int count = 0;
System.setOut(newFile);
while (lineScan.hasNextLine())
{
String pop = lineScan.nextLine();
String s1 = 1920 + (10*count) + ": " + pop;
System.out.println(s1);
count++;
}
newFile.close();
}
}
I could not see flush()/close() being called anywhere (Outside the if block).
flush()/close() needs to be called on the PrintStream object to actually perform write to the underlying output Stream(File, in your case).
The problem is you are reading the text of the file name, not the file itself, to use the Scanner class to read a file you can use a file object like you did so in the PrintStream.
Fixed Code:
public static void writeToFile (String a, String username) throws FileNotFoundException {
Scanner lineScan = new Scanner (new File(a));
String name = lineScan.next();
PrintStream newFile = new PrintStream (new File (username+".txt"));
//The below newFile command works
newFile.println(username);
if ((username.toUpperCase()).equals(name.toUpperCase()))
{
int count = 0;
while (lineScan.hasNextInt())
{
int pop = lineScan.nextInt();
String s1 = 1920 + (10*count) + ": " + pop;
newFile.println(s1);
count++;
}
}
newFile.close();
lineScan.close();
}

Using formulas from a text/writing to a text

So, my lecture powerpoint slides and even my book is not really doing a good job (for my understanding that is) of explaining how to use formulas from a text document, then when the code runs/compiles successfully it will create a "Results.txt" in the same folder.
These are the formulas in a notepad doc. Nothing to crazy, just a proof of concept
4 * 5 ..
3 / 4...
3 - 1..
2 + 3..
import java.io.*;
import java.util.*;
public class ReadFileLineByLine {
public static void main(String[] args) throws FileNotFoundException {
String line;
int numberOfLines = 3;
String[] textData = new String[numberOfLines];
int i;
for(i = 0; i < numberOfLines; i++){
textData[i] = textReader.readLine();
}
text.Reader.close();
return textData;
try {
File inputfile = new File(args[0]); //new File("formulas.txt")
Scanner input = new Scanner(new File("C:\Users\Frost\Documents\Question4"));
BuffredReader br = new BufferedReader(new FileReader("C:\Users\Frost\Documents\Question4"));
PrintWriter output = new PrintWriter("Results.txt");
while (input.hasNextLine()) {
line = input.nextLine();
System.out.println("read <" + line + ">"); // Display message to commandline
// Declare ArrayList of for storing tokenized formula from String line
double result = 0; // The variable to store result of the operation
// Determine the operator and calculate value of the result
System.out.println(formula.get(0) + ' ' + formula.get(1) + ' ' +
formula.get(2) + " = " + result); // Display result to command line
// Write result to file
}
// Need to close input and output files
}
catch (FileNotFoundException e) {
System.out.println("Error reading file named " + Formulas.txt);
}
}
}
Here's something to get you started. The //TODO: comments are where you need to build your logic. Be sure to change the file paths back to what you need. I changed them to a Temp location. Also change the messages printed as I just put something there as proof of concept. I tried to comment thoroughly but don't hesitate to ask questions.
import java.io.*;
import java.util.*;
public class ReadFileLineByLine {
public static void main(String[] args) throws FileNotFoundException {
String line = "";
//Declare Scanner and PrintWriter outside of try clause so they can be closed in finally clause
Scanner input = null;
PrintWriter output = null;
try {
//Instantiate input and output file
input = new Scanner(new File("C:\\Temp\\test.txt"));
output = new PrintWriter(new File("C:\\Temp\\Results.txt"));
//Loop through lines in input file
while (input.hasNextLine()) {
line = input.nextLine();
// Display message to commandline
System.out.println("read <" + line + ">");
// Populate ArrayList of tokenized formula from String line
//TODO:
// The variable to store result of the operation
double result = 0;
// Determine the operator and calculate value of the result
//TODO:
// Write result to file
output.println("Print result of " + line + " to Results.txt");
}
} catch (FileNotFoundException e) {
//Exception thrown, print message to console
System.out.println("File Not Found: " + e.getMessage());
} finally {
//close files in finally clause so it happens even if exception is thrown
//I also set to null as extra precaution
input.close();
input = null;
output.close();
output = null;
}
}
}

Storing an array of strings without initializing the size

Background: This program reads in a text file and replaces a word in the file with user input.
Problem: I am trying to read in a line of text from a text file and store the words into an array.
Right now the array size is hard-coded with an number of indexes for test purposes, but I want to make the array capable of reading in a text file of any size instead.
Here is my code.
public class FTR {
public static Scanner input = new Scanner(System.in);
public static Scanner input2 = new Scanner(System.in);
public static String fileName = "C:\\Users\\...";
public static String userInput, userInput2;
public static StringTokenizer line;
public static String array_of_words[] = new String[19]; //hard-coded
/* main */
public static void main(String[] args) {
readFile(fileName);
wordSearch(fileName);
replace(fileName);
}//main
/*
* method: readFile
*/
public static void readFile(String fileName) {
try {
FileReader file = new FileReader(fileName);
BufferedReader read = new BufferedReader(file);
String line_of_text = read.readLine();
while (line_of_text != null) {
System.out.println(line_of_text);
line_of_text = read.readLine();
}
} catch (Exception e) {
System.out.println("Unable to read file: " + fileName);
System.exit(0);
}
System.out.println("**************************************************");
}
/*
* method: wordSearch
*/
public static void wordSearch(String fileName) {
int amount = 0;
System.out.println("What word do you want to find?");
userInput = input.nextLine();
try {
FileReader file = new FileReader(fileName);
BufferedReader read = new BufferedReader(file);
String line_of_text = read.readLine();
while (line_of_text != null) { //there is a line to read
System.out.println(line_of_text);
line = new StringTokenizer(line_of_text); //tokenize the line into words
while (line.hasMoreTokens()) { //check if line has more words
String word = line.nextToken(); //get the word
if (userInput.equalsIgnoreCase(word)) {
amount += 1; //count the word
}
}
line_of_text = read.readLine(); //read the next line
}
} catch (Exception e) {
System.out.println("Unable to read file: " + fileName);
System.exit(0);
}
if (amount == 0) { //if userInput was not found in the file
System.out.println("'" + userInput + "'" + " was not found.");
System.exit(0);
}
System.out.println("Search for word: " + userInput);
System.out.println("Found: " + amount);
}//wordSearch
/*
* method: replace
*/
public static void replace(String fileName) {
int amount = 0;
int i = 0;
System.out.println("What word do you want to replace?");
userInput2 = input2.nextLine();
System.out.println("Replace all " + "'" + userInput2 + "'" + " with " + "'" + userInput + "'");
try {
FileReader file = new FileReader(fileName);
BufferedReader read = new BufferedReader(file);
String line_of_text = read.readLine();
while (line_of_text != null) { //there is a line to read
line = new StringTokenizer(line_of_text); //tokenize the line into words
while (line.hasMoreTokens()) { //check if line has more words
String word = line.nextToken(); //get the word
if (userInput2.equalsIgnoreCase(word)) {
amount += 1; //count the word
word = userInput;
}
array_of_words[i] = word; //add word to index in array
System.out.println("WORD: " + word + " was stored in array[" + i + "]");
i++; //increment array index
}
//THIS IS WHERE THE PRINTING HAPPENS
System.out.println("ARRAY ELEMENTS: " + Arrays.toString(array_of_words));
line_of_text = read.readLine(); //read the next line
}
BufferedWriter outputWriter = null;
outputWriter = new BufferedWriter(new FileWriter("C:\\Users\\..."));
for (i = 0; i < array_of_words.length; i++) { //go through the array
outputWriter.write(array_of_words[i] + " "); //write word from array to file
}
outputWriter.flush();
outputWriter.close();
} catch (Exception e) {
System.out.println("Unable to read file: " + fileName);
System.exit(0);
}
if (amount == 0) { //if userInput was not found in the file
System.out.println("'" + userInput2 + "'" + " was not found.");
System.exit(0);
}
}//replace
}//FTR
You can use java.util.ArrayList (which dynamically grows unlike an array with fixed size) to store the string objects (test file lines) by replacing your array with the below code:
public static List<String> array_of_words = new java.util.ArrayList<>();
You need to use add(string) to add a line (string) and get(index) to retrieve the line (string)
Please refer the below link for more details:
http://docs.oracle.com/javase/8/docs/api/java/util/ArrayList.html
You may want to give a try to ArrayList.
In Java normal arrays cannot be initialized without giving initial size and they cannot be expanded during run time. Whereas ArrayLists have resizable-array implementation of the List interface.ArrayList also comes with number of useful builtin functions such as
Size()
isEmpty()
contains()
clone()
and others. On top of these you can always convert your ArrayList to simple array using ArrayList function toArray(). Hope this answers your question. I'll prepare some code and share with you to further explain things you can achieve using List interface.
Use not native [] arrays but any kind of java collections
List<String> fileContent = Files.readAllLines(Paths.get(fileName));
fileContent.stream().forEach(System.out::println);
long amount = fileContent.stream()
.flatMap(line -> Arrays.stream(line.split(" +")))
.filter(word -> word.equalsIgnoreCase(userInput))
.count();
List<String> words = fileContent.stream()
.flatMap(line -> Arrays.stream(line.split(" +")))
.filter(word -> word.length() > 0)
.map(word -> word.equalsIgnoreCase(userInput) ? userInput2 : word)
.collect(Collectors.toList());
Files.write(Paths.get(fileName), String.join(" ", words).getBytes());
of course you can works with such lists more traditionally, with loops
for(String line: fileContent) {
...
}
or even
for (int i = 0; i < fileContent.size(); ++i) {
String line = fileContent.get(i);
...
}
i just like streams :)

Creating the program of tokenization

I need a help. I have to write a program of tokenization. I load a text file and split it into tokens, but I also need to display the final, initial position of the words and the word length (from text file). I’ll be very grateful to you for any help. I've been trying to do this for the past 3 days with no luck, here is what I have done:
import java.util.StringTokenizer;
import java.io.*;
public class Tokenizer1 {
public static void main(String[] args) throws FileNotFoundException, IOException {
BufferedReader br = new BufferedReader(new FileReader("C://text.txt"));
FileWriter fw=new FileWriter("C://result.txt");
PrintWriter pw=new PrintWriter(fw);
StringTokenizer st = new StringTokenizer(br.readLine()," ");
while (st.hasMoreTokens()) {
System.out.println(st.nextToken());
}
String[] tokens = "".split(",");
int tokenStartIndex = 0;
for (String token : tokens) {
for (String token : str.split(", ")) {
System.out.println("token: " + token + ", tokenStartIndex: " + tokenStartIndex);
tokenStartIndex += token.length() + 1;
}
}
}
Try this one if you don't need to process the file line by line:
public static void main(String[] args) throws FileNotFoundException, IOException {
FileInputStream fis = new FileInputStream("C:/text.txt");
StringBuilder sb = new StringBuilder();
int c;
while((c = fis.read()) != -1) {
sb.append((char)c);
}
fis.close();
System.out.println(sb.toString());
System.out.println("---------------------");
int start = 0;
// OPTION 1: using String.split method
String[] tokens = sb.toString().split("[\\s,]+");
for(String t : tokens) {
System.out.println("START: " + start + "\tLENGTH: " + t.length() + "\tWORD: " + t);
start += t.length();
}
start = 0;
// OPTION 2: using StringTokenizer class
StringTokenizer st = new StringTokenizer(sb.toString(), ",\t\n\f\r");
while(st.hasMoreTokens()) {
String next = st.nextToken();
System.out.println("START: " + start + "\tLENGTH: " + next.length() + "\tWORD: " + next);
start += next.length();
}
}
If you need to process the file line by line, you might wanna try this one:
public static void main(String[] args) throws FileNotFoundException, IOException {
BufferedReader br = new BufferedReader(new FileReader("C:/text.txt"));
StringBuilder sb = new StringBuilder();
String line;
int lineNumber = -1;
while ((line = br.readLine()) != null) {
++lineNumber;
sb.append(line);
System.out.println("\nLINE: " + lineNumber);
int elementPosition = 0;
// OPTION 1: using String.split method
/*String[] lineContents = line.split("[\\s,]+");
for (String content : lineContents) {
System.out.println("\tSTART: " + elementPosition + "\tLENGTH: " + content.length() + "\tWORD: " + content);
elementPosition += content.length();
}*/
// OPTION 2: using StringTokenizer class
StringTokenizer st = new StringTokenizer(sb.toString(), ",\t\n\f\r");
while(st.hasMoreTokens()) {
String next = st.nextToken();
System.out.println("\tSTART: " + elementPosition + "\tLENGTH: " + next.length() + "\tWORD: " + next);
elementPosition += next.length();
}
}
br.close();
}
I hope this helps.

Categories