Java is not my main programming language so I might be asking the obvious.
But is there a simple file-handling library in Java, like in python?
For example I just want to say:
File f = Open('file.txt', 'w')
for(String line:f){
//do something with the line from file
}
Thanks!
UPDATE: Well, the stackoverflow auto-accepted a weird answer. It has to do with bounty that I placed - so if you want to see other answers, just scroll down!
I was thinking something more along the lines of:
File f = File.open("C:/Users/File.txt");
for(String s : f){
System.out.println(s);
}
Here is my source code for it:
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
import java.util.Iterator;
public abstract class File implements Iterable<String>{
public final static String READ = "r";
public final static String WRITE = "w";
public static File open(String filepath) throws IOException{
return open(filepath, READ);
}
public static File open(String filepath, String mode) throws IOException{
if(mode == READ){
return new ReadableFile(filepath);
}else if(mode == WRITE){
return new WritableFile(filepath);
}
throw new IllegalArgumentException("Invalid File Write mode '" + mode + "'");
}
//common methods
public abstract void close() throws IOException;
// writer specific
public abstract void write(String s) throws IOException;
}
class WritableFile extends File{
String filepath;
Writer writer;
public WritableFile(String filepath){
this.filepath = filepath;
}
private Writer writer() throws IOException{
if(this.writer == null){
writer = new BufferedWriter(new FileWriter(this.filepath));
}
return writer;
}
public void write(String chars) throws IOException{
writer().write(chars);
}
public void close() throws IOException{
writer().close();
}
#Override
public Iterator<String> iterator() {
return null;
}
}
class ReadableFile extends File implements Iterator<String>{
private BufferedReader reader;
private String line;
private String read_ahead;
public ReadableFile(String filepath) throws IOException{
this.reader = new BufferedReader(new FileReader(filepath));
this.read_ahead = this.reader.readLine();
}
private Reader reader() throws IOException{
if(reader == null){
reader = new BufferedReader(new FileReader(filepath));
}
return reader;
}
#Override
public Iterator<String> iterator() {
return this;
}
#Override
public void close() throws IOException {
reader().close();
}
#Override
public void write(String s) throws IOException {
throw new IOException("Cannot write to a read-only file.");
}
#Override
public boolean hasNext() {
return this.read_ahead != null;
}
#Override
public String next() {
if(read_ahead == null)
line = null;
else
line = new String(this.read_ahead);
try {
read_ahead = this.reader.readLine();
} catch (IOException e) {
read_ahead = null;
reader.close()
}
return line;
}
#Override
public void remove() {
// do nothing
}
}
and here is the unit-test for it:
import java.io.IOException;
import org.junit.Test;
public class FileTest {
#Test
public void testFile(){
File f;
try {
f = File.open("File.java");
for(String s : f){
System.out.println(s);
}
} catch (IOException e) {
e.printStackTrace();
}
}
#Test
public void testReadAndWriteFile(){
File from;
File to;
try {
from = File.open("File.java");
to = File.open("Out.txt", "w");
for(String s : from){
to.write(s + System.getProperty("line.separator"));
}
to.close();
} catch (IOException e1) {
e1.printStackTrace();
}
}
}
Reading a file line by line in Java:
BufferedReader in = new BufferedReader(new FileReader("myfile.txt"));
String line;
while ((line = in.readLine()) != null) {
// Do something with this line
System.out.println(line);
}
in.close();
Most of the classes for I/O are in the package java.io. See the API documentation for that package. Have a look at Sun's Java I/O tutorial for more detailed information.
addition: The example above will use the default character encoding of your system to read the text file. If you want to explicitly specify the character encoding, for example UTF-8, change the first line to this:
BufferedReader in = new BufferedReader(
new InputStreamReader(new FileInputStream("myfile.txt"), "UTF-8"));
If you already have dependencies to Apache commons lang and commons io this could be an alternative:
String[] lines = StringUtils.split(FileUtils.readFileToString(new File("myfile.txt")), '\n');
for(String line: lines){
//do something with the line from file
}
(I would prefer Jesper's answer)
If you want to iterate through a file by strings, a class you might find useful is the Scanner class.
import java.io.*;
import java.util.Scanner;
public class ScanXan {
public static void main(String[] args) throws IOException {
Scanner s = null;
try {
s = new Scanner(new BufferedReader(new FileReader("myFile.txt")));
while (s.hasNextLine()) {
System.out.println(s.nextLine());
}
} finally {
if (s != null) {
s.close();
}
}
}
}
The API is pretty useful: http://java.sun.com/javase/7/docs/api/java/util/Scanner.html
You can also parse the file using regular expressions.
I never get tired of pimping Google's guava-libraries, which takes a lot of the pain out of... well, most things in Java.
How about:
for (String line : Files.readLines(new File("file.txt"), Charsets.UTF_8)) {
// Do something
}
In the case where you have a large file, and want a line-by-line callback (rather than reading the whole thing into memory) you can use a LineProcessor, which adds a bit of boilerplate (due to the lack of closures... sigh) but still shields you from dealing with the reading itself, and all associated Exceptions:
int matching = Files.readLines(new File("file.txt"), Charsets.UTF_8, new LineProcessor<Integer>(){
int count;
Integer getResult() {return count;}
boolean processLine(String line) {
if (line.equals("foo")
count++;
return true;
}
});
If you don't actually want a result back out of the processor, and you never abort early (the reason for the boolean return from processLine) you could then do something like:
class SimpleLineCallback extends LineProcessor<Void> {
Void getResult{ return null; }
boolean processLine(String line) {
doProcess(line);
return true;
}
abstract void doProcess(String line);
}
and then your code might be:
Files.readLines(new File("file.txt"), Charsets.UTF_8, new SimpleLineProcessor(){
void doProcess(String line) {
if (line.equals("foo");
throw new FooException("File shouldn't contain 'foo'!");
}
});
which is correspondingly cleaner.
public static void main(String[] args) throws FileNotFoundException {
Scanner scanner = new Scanner(new File("scan.txt"));
try {
while (scanner.hasNextLine()) {
System.out.println(scanner.nextLine());
}
} finally {
scanner.close();
}
}
Some caveats:
That uses the default system encoding, but you should specify the file encoding
Scanner swallows I/O exceptions, so you may want to check ioException() at the end for proper error handling
Simple example using Files.readLines() from guava-io with a LineProcessor callback:
import java.io.File;
import java.io.IOException;
import com.google.common.base.Charsets;
import com.google.common.io.Files;
import com.google.common.io.LineProcessor;
public class GuavaIoDemo {
public static void main(String[] args) throws Exception {
int result = Files.readLines(new File("/home/pascal/.vimrc"), //
Charsets.UTF_8, //
new LineProcessor<Integer>() {
int counter;
public Integer getResult() {
return counter;
}
public boolean processLine(String line) throws IOException {
counter++;
System.out.println(line);
return true;
}
});
}
}
You could use jython which lets you run Python syntax in Java.
Nice example here: Line by line iteration
Try looking at groovy!
Its a superset of Java that runs in hte JVM. Most valid Java code is also valid Groovy so you have access any of the million java APIs directly.
In addition it has many of the higher level contructs familiar to Pythonists, plus
a number of extensions to take the pain out of Maps, Lists, sql, xml and you guessed it -- file IO.
Related
I'm new to java and I'm having a little problem with my code. There's no error and such, it just keeps saying process finished but no output was displayed. The filename is correct as I've checked.
import java.nio.file.;
import java.io.;
public class GuessingGame {
public GuessingGame() {
String filename = "C:\\Users\\angela\\Documents\\words.txt";
Path path = Paths.get(filename.toString());
try {
InputStream input = Files.newInputStream(path);
BufferedReader read = new BufferedReader(new InputStreamReader(input));
String word = null;
while((word = read.readLine()) !=null) {
System.out.println(word);
}
}
catch(IOException ex) {
}
}
public static void main (String[] args) {
new GuessingGame();
}
}
You are ignoring the exception and you don't close the file. Save some typing by using the built-in input.transferTo() for copying the file to System.out, and pass on the exception for the caller to handle by adding throws IOException to constructor and main.
Replace your try-catch block with this try-with-resources, which handles closing the file after use:
try (InputStream input = Files.newInputStream(path)) {
input.transferTo(System.out) ;
}
You managed to call the intended class, but you also needed to specify the specific function which you have declared in the function. Like so:
public static void main (String[] args) { GuessingGame gg = new GuessingGame; gg.GuessingGame(); }
I have a record in a CSV file and i am trying to add some extra info (a name) to the same specific record with the following code but it does not work. There is no error shown but the info i am trying to add just does not appear. What am i missing ?
public class AddName {
public static void main(String[] args) {
String filepath="Zoo.csv";
String editTerm="Fish";
String addedName="Ron";
addToRecord(filepath,editTerm,addedName);
}
public static void addToRecord(String filepath,String editTerm,String addedName){
String animal= "";
try{
FileWriter fw=new FileWriter(filepath,true);
BufferedWriter bw=new BufferedWriter(fw);
PrintWriter pw=new PrintWriter(bw);
if (animal.equals(editTerm)){
pw.println(editTerm+","+addedName);
pw.flush();
pw.close();
}
System.out.println("Your Record was saved");
}
catch(Exception e){
System.out.println("Your Record was not saved");
e.printStackTrace();
}
}
You could consider using a CSV library to help you out with parsing CSVs because it is more complicated than it looks, especially when it comes down to quoting.
Here's a quick example using OpenCSV that clones the original CSV file and adds "Ron" as necessary:
public class Csv1 {
public static void main(String[] args) throws IOException, CsvValidationException {
addToRecord("animal.csv", "animal-new.csv", "fish", "Ron");
}
public static void addToRecord(String filepathIn, String filepathOut, String editTerm, String addedName)
throws IOException, CsvValidationException {
try (CSVReader reader = new CSVReader(new FileReader(filepathIn))) {
try (CSVWriter writer = new CSVWriter(new FileWriter(filepathOut))) {
String[] values;
while ((values = reader.readNext()) != null) {
if (values.length > 2 && values[0].equals(editTerm)) {
values[1] = addedName;
}
writer.writeNext(values);
}
}
}
}
}
Given the file:
type,name,age
fish,,10
cat,,12
lion,tony,10
will produce:
"type","name","age"
"fish","Ron","10"
"cat","","12"
"lion","tony","10"
(You can look for answers about outputting quotes in the resulting CSV)
Here the requirement is to add an extra column if the animal name matches. It's equivalent to changing a particular line in a file. Here's a simple approach to achieve the same, (Without using any extra libraries),
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;
public class EditLineInFile {
public static void main(String[] args) {
String animal = "Fish";
Path path = Paths.get("C:\\Zoo.csv");
try {
List<String> allLines = Files.readAllLines(path);
int counter = 0;
for (String line : allLines) {
if (line.equals(animal)) {
line += ",Ron";
allLines.set(counter, line);
}
counter++;
}
Files.write(path, allLines);
} catch (IOException e) {
e.printStackTrace();
}
}
}
You may use this code to replace the file content "Fish" to "Fish, Ron"
public static void addToRecord(String filepath, String editTerm, String addedName) {
try (Stream<String> input = Files.lines(Paths.get(filepath));
PrintWriter output = new PrintWriter("Output.csv", "UTF-8"))
{
input.map(s -> s.replaceAll(editTerm, editTerm + "," + addedName))
.forEachOrdered(output::println);
} catch (IOException e) {
e.printStackTrace();
}
}
I have this code set up and I am trying to write a program that looks through a file and finds a specific hidden secret word then replaces the word with "found!" then re-prints the text file in the console. I know how to use reader and writer but I am unsure how i can use them in unison to do this. Code is as follows:
Reader Class:
package Main;
import java.io.*;
public class Read {
private static String line;
FileReader in;
File file;
public Read() {
line = "";
}
public void readFile() throws IOException {
file = new File("C:examplePathName\\ReadWriteExp.txt");
in = new FileReader(file);
BufferedReader br = new BufferedReader(in);
while((line = br.readLine()) != null) {
System.out.println(line);
}
in.close();
}
public String getLine() {
return line;
}
public File getFile() {
return file;
}
}
Writer(change) class:
package Main;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
public class Change {
public static void main(String[] args) throws IOException{
Read r = new Read();
String line = r.getLine();
FileWriter fw = new FileWriter(r.getFile());
while(line != null) {
if(line.equals("example")) {
fw.write("found!");
}
System.out.println(line);
}
}
}
Am i on the right path or should i combine both of these into one class. Also is this the proper way of writing to a specific line in a text file?
If the file is a reasonable size, you can read it into memory, change what you need and write it back out again:
public static void replaceOccurrences(String match, String replacement, Path path) throws IOException {
Files.write(path, Files.lines(path).map(l -> {
if(l.contains(match)) {
return l.replace(match, replacement);
} else {
return l;
}
}).collect(Collectors.toList()));
}
Alternatively, if you know that the search term occurs only once and you just need to find the position of the occurrence, use the following:
try(BufferedReader reader = Files.newBufferedReader(path)) {
int lineIndex = 0;
String line;
while(!(line = reader.readLine()).contains(match)) {
lineIndex++;
}
System.out.println(lineIndex); // line which contains match, 0-indexed
System.out.println(line.indexOf(match)); // starting position of match in line, 0-indexed
}
If all you have to do is print the converted text to system out (rather than writing it out to a file), the second class isn't really needed. You can accomplish what you need in the readFile() method of the Read class:
public void readFile() throws IOException {
file = new File("C:examplePathName\\ReadWriteExp.txt");
in = new FileReader(file);
BufferedReader br = new BufferedReader(in);
while((line = br.readLine()) != null) {
System.out.println(line.replaceAll("example", "found!"));
}
in.close();
}
There are a lot of other tweaks you could make, but that's the core of the functionality you specified in your question.
A Java program on CodeEval had to accept a file path as an argument. I used a command line argument to do this, but I get an exception as below when I submitted my code on CodeEval. What are some potential solutions to this problem?
Exception in thread "main" java.util.NoSuchElementException
at java.util.StringTokenizer.nextToken(StringTokenizer.java:349)
at java.util.StringTokenizer.nextElement(StringTokenizer.java:407)
at Main.FileRead(Main.java:61)
at Main.main(Main.java:26)
Here's the boilerplate Java code that I use for my Codeeval code. The specific problem code generally goes in the processLine method. I don't use Scanner or StringTokenizer. I use the String split method to process the input.
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
public class Main implements Runnable {
private String fileName;
public Main (String fileName) {
this.fileName = fileName;
}
#Override
public void run() {
try {
processFile();
} catch (IOException e) {
e.printStackTrace();
}
}
private void processFile() throws IOException {
BufferedReader br = new BufferedReader(
new FileReader(fileName));
String line = "";
while ((line = br.readLine()) != null) {
processLine(line);
}
br.close();
}
private void processLine(String line) {
System.out.println(line);
}
public static void main(String[] args) {
new Main(args[0]).run();
}
}
Firstly, Check the name of class.Class name should be 'Main'.
Second you have to give all the imports in CodeEval Editor which you are using in your program.
This happens if you don't check to see if there are any more tokens (by calling hasMoreTokens). If no more tokens exist and you call nextToken, you will get this exception. However, without seeing the rest of your code, there is no way to know what is actually happening.
I'm trying to make it so my program
chooses a file
reads the code one line at a time
uses an interface to do three different things
convert to uppercase
count the number of characters
save to a file ("copy.txt")
I'm stuck with the formatting parts. For instance, I'm not sure where the println commands needs to be. Any help will definitely be appreciated. I'm a beginner and still learning basic things.
Interface for Processing Individual Strings:
public interface StringProcessor
{
void process(String s);
}
Processing Class:
import java.util.Scanner;
import java.io.FileNotFoundException;
import java.io.File;
import javax.swing.JFileChooser;
class FileProcessor
{
private Scanner infile;
public FileProcessor(File f) throws FileNotFoundException
{
Scanner infile = new Scanner(System.in);
String line = infile.nextLine();
}
public String go(StringProcessor a)
{
a.process(line);
}
}
Driver Class:
import java.util.Scanner;
import java.io.FileNotFoundException;
import java.io.File;
import javax.swing.JFileChooser;
public class Driver
{
public static void main(String[] args) throws FileNotFoundException
{
JFileChooser chooser = new JFileChooser();
File inputFile = null;
if (chooser.showOpenDialog(null) == JFileChooser.APPROVE_OPTION)
{
inputFile = chooser.getSelectedFile();
}
FileProcessor infile = new FileProcessor(inputFile);
int total=0;
}
}
This Would Make Each Line Uppercase:
public class Upper implements StringProcessor
{
public void process(String s)
{
while (infile.hasNextLine())
{
System.out.println(infile.nextLine().toUpperCase());
}
}
}
This Would Count Characters:
public class Count implements StringProcessor
{
public void process(String s)
{
while (infile.hasNextLine())
{
int charactercounter = infile.nextLine().length();
total = total+charactercounter;
}
}
}
This Would Print to a File:
import java.io.PrintWriter;
import java.io.FileNotFoundException;
public class Print implements StringProcessor
{
public void process(String s)
{
PrintWriter out = new PrintWriter("copy.txt");
while (infile.hasNextLine())
{
out.println(infile.nextLine());
}
out.close();
}
}
Java was one of the first programming languages I learned and once you get it, it's so beautiful. Here is the solution for you homework, but now you have a new homework assignment. Go and figure out what is doing what and label it with notes. So next time you have a similar problem you can go over your old codes and cherry pick what you need. We were all noobs at some point so don't take it to bad.
StringProcessor.java
public interface StringProcessor {
public String Upper(String str);
public int Count(String str);
public void Save(String str, String filename);
}
FileProcessor.java
import java.io.FileWriter;
public class FileProcessor implements StringProcessor{
public FileProcessor(){
}
// Here we get passed a string and make it UpperCase
#Override
public String Upper(String str) {
return str.toUpperCase();
}
// Here we get passed a string and return the length of it
#Override
public int Count(String str) {
return str.length();
}
// Here we get a string and a file name to save it as
#Override
public void Save(String str, String filename) {
try{
FileWriter fw = new FileWriter(filename);
fw.write(str);
fw.flush();
fw.close();
}catch (Exception e){
System.err.println("Error: "+e.getMessage());
System.err.println("Error: " +e.toString());
}finally{
System.out.println ("Output file has been created: " + filename);
}
}
}
Driver.java
import java.io.File;
import java.util.Scanner;
import javax.swing.JFileChooser;
public class Driver {
#SuppressWarnings("resource")
public static void main(String[] args){
System.out.println("Welcome to the File Processor");
Scanner scan = new Scanner(System.in);
System.out.print("\nWould you like to begin? (yes or no): ");
String startProgram = scan.next();
if(startProgram.equalsIgnoreCase("yes")){
System.out.println("\nSelect a file.\n");
JFileChooser chooser = new JFileChooser();
File inputFile = null;
if(chooser.showOpenDialog(null) == JFileChooser.APPROVE_OPTION){
inputFile = new File(chooser.getSelectedFile().getAbsolutePath());
try{
Scanner file = new Scanner(inputFile);
file.useDelimiter("\n");
String data = "";
FileProcessor fp = new FileProcessor();
while (file.hasNext()){
String line = file.next();
System.out.println("Original: " +line);
System.out.println("To Upper Case: " +fp.Upper(line));
System.out.println("Count: " +fp.Count(line));
System.out.println();
data += line;
}
System.out.println("\nFile Processing complete!\n");
System.out.print("Save copy of file? (yes or no): ");
String save = scan.next();
if(save.equalsIgnoreCase("yes")){
fp.Save(data, "copy.txt");
System.out.println("\nProgram Ending... Goodbye!");
}else{
System.out.println("\nProgram Ending... Goodbye!");
}
}catch (Exception e){
e.printStackTrace();
}
}
}else{
System.out.println("\nProgram Ending... Goodbye!");
}
}
}
text.txt
some text here to test the file
and to see if it work correctly
Just a note when you save the file "copy.txt", it will show up in your project folder.
As your problem operates on streams of characters, there is already a good Java interface to implement. Actually, they are two abstract classes: FilterReader or FilterWriter — extending either one will work. Here, I've chosen to extend FilterWriter.
For example, here is an example of a Writer that keeps track of how many characters it has been asked to write:
import java.io.*;
public class CharacterCountingWriter extends FilterWriter {
private long charCount = 0;
public CharacterCountingWriter(Writer out) {
super(out);
}
public void write(int c) throws IOException {
this.charCount++;
out.write(c);
}
public void write(char[] buf, int off, int len) throws IOException {
this.charCount += len;
out.write(buf, off, len);
}
public void write(String str, int off, int len) throws IOException {
this.charCount += len;
out.write(str, off, len);
}
public void resetCharCount() {
this.charCount = 0;
}
public long getCharCount() {
return this.charCount;
}
}
Based on that model, you should be able to implement a UpperCaseFilterWriter as well.
Using those classes, here is a program that copies a file, uppercasing the text and printing the number of characters in each line as it goes.
public static void main(String[] args) throws IOException {
BufferedReader in = new BufferedReader(new FileReader(args[0]));
try (CharacterCountingWriter ccw = new CharacterCountingWriter(new FileWriter(args[1]));
UpperCaseFilterWriter ucfw = new UpperCaseFilterWriter(ccw);
Writer pipeline = ucfw) { // pipeline is just a convenient alias
String line;
while (null != (line = in.readLine())) {
// Print count of characters in each line, excluding the line
// terminator
ccw.resetCharCount();
pipeline.write(line);
System.out.println(ccw.getCharCount());
pipeline.write(System.lineSeparator());
}
pipeline.flush();
}
}