Java reading and writing to same file - java

I'm using the following code to search specific files in my computer and write the absolute path in a text file. My problem is that every time I run this code it add duplicate lines into text file, i want to add only those lines(file path) which are not written in the text file at that time (no duplicates).. Thank you
public static void walkin(File dir) {
String pattern = ".mp4";
try {
PrintWriter out = new PrintWriter(new BufferedWriter(
new FileWriter("D:\\nawaaaaaa.txt", true)));
File listFile[] = dir.listFiles();
if (listFile != null) {
for (int i = 0; i < listFile.length; i++) {
if (listFile[i].isDirectory()) {
walkin(listFile[i]);
} else if (listFile[i].getName().endsWith(pattern)
&& listFile[i].isFile()) {
System.out.println(listFile[i].getPath());
out.write(listFile[i].toString());
out.write("\r\n");
// out.close();
} else {
walkin(listFile[i]);
}
}
}
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}

Your code works for me, no idea what is the problem on your side, how you are calling it; but you can optimize your code a bit, something as follows (just very quick code, code be made nicer, but to give you an idea):
public class SomeTest {
private static HashSet<String> filez = new HashSet<String> ();
public static void walkin(File dir, PrintWriter out) {
String pattern = ".mp4";
File listFile[] = dir.listFiles();
if (listFile != null) {
for (int i = 0; i < listFile.length; i++) {
if (listFile[i].getName().endsWith(pattern) && listFile[i].isFile()) {
//System.out.println(listFile[i].getPath());
if (filez.add(listFile[i].getPath())) {
out.write(listFile[i].toString());
out.write("\r\n");
}
} else {
walkin(listFile[i], out);
}
}
}
}
public static void main(String[] args) {
try {
File dir = new File("C:\\mydir");
PrintWriter out = new PrintWriter(new BufferedWriter(
new FileWriter("D:\\nawaaaaaa.txt", true)));
walkin(dir, out);
out.close();
} catch (IOException e) {
//
}
}
}
You can use the filez hashset to print stuff, or write your file at the end of the parsing process as well.. your choice.

If you don't want duplicates in the file, you will need to keep track of the file names you have already written. A HashSet<String> is going for this. But I'm surprised the above code works at all given that you keep opening the file at the top of walkin() and walkin() itself is recursive. You need to rethink your code a bit. Possibly passing the PrintWriter into walkin() as a parameter.

Since you are running the code multiple times ("every time I run this code it add duplicate lines into text file"), so once you finish writing to the file, you read each line and store it in a HashSet<String>. And use another writer to write it to the file.
BufferedWriter writer = new BufferedWriter(new FileWriter("filename"));
for (String eachUniqueLine: `Your hash set`) {
writer.write(eachUniqueLine);
writer.newLine();
}
(It is costly as in you have to do more i/o operation)

You need to expand your method into a class that perform this kind of tasks.
You have two main problem you open a writer for each directory and you call the walkin, for things that do not apply to your logic (and open writer again).
You should try to design a class that will be able to create an index for you.
public static void main(String[] args) throws IOException {
File createTempFile = File.createTempFile("mp4", ".idx");
FileIndexer fi = new FileIndexer(createTempFile.getAbsolutePath());
fi.index("C:\\", "mp4");
System.out.println(createTempFile);
}
public static class FileIndexer {
private static final String END_OF_LINE = "\r\n";
private final String outputPath;
private final Set<String> index = new HashSet<String>();
public FileIndexer(String outputPath) {
this.outputPath = outputPath;
}
private boolean isValidPath(String path) {
return outputPath != null && outputPath.trim().length() > 0;
}
private boolean isValidIndexFile(File file) {
return file.isFile() && file.canRead() && file.canWrite();
}
private void createIndexFile(File file) throws IOException {
if(file.createNewFile() == false) {
throw new IOException("Could not create index file");
}
this.index.clear();
}
private void readIndexFile(File file) throws IOException {
isValidIndexFile(file);
index.clear();
BufferedReader bufferedReader = null;
try {
bufferedReader = new BufferedReader(new FileReader(file));
String line;
while((line = bufferedReader.readLine()) != null) {
addToIndex(line);
}
} finally {
if(bufferedReader != null) {
bufferedReader.close();
}
}
}
private void addToIndex(String line) {
index.add(line);
}
private PrintWriter openIndex() throws IOException {
if(isValidPath(outputPath) == false) {
throw new IOException(String.format("The outputPath is not valid: [%s]",outputPath));
}
File indexFile = new File(outputPath);
if(indexFile.exists()) {
readIndexFile(indexFile);
} else {
createIndexFile(indexFile);
}
return new PrintWriter(new BufferedWriter(new FileWriter(this.outputPath, true)));
}
public synchronized void index(String pathToIndex, String pattern) throws IOException {
isValidPath(pathToIndex);
PrintWriter out = openIndex();
try {
File elementToIndex = new File(pathToIndex);
index(elementToIndex,pathToIndex, out);
} finally {
if(out != null) {
out.close();
}
}
}
private void index(File elementToIndex, String pattern, PrintWriter out) {
if(elementToIndex == null) {
return;
}
if(elementToIndex.isDirectory()) {
for(File file : elementToIndex.listFiles()) {
index(file,pattern, out);
}
}
if(elementToIndex.isFile() && elementToIndex.getAbsolutePath().endsWith(pattern)) {
writeToIndex(elementToIndex, out);
}
}
private void writeToIndex(File elementToIndex, PrintWriter out) {
out.write(elementToIndex.getAbsolutePath());
out.write(END_OF_LINE);
}
}

Problem Solved (BTW i'm not sure if it is most efficient solution or not ).......
public static void main(String[] args) {
try {
File dir = new File("D:\\To Do");
BufferedWriter out = new BufferedWriter(new FileWriter(
"D:\\path.txt", true));
walkin(dir, out);
out.close();
readfile();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} // Replace this with a suitable directory
// walkin(new File("D:/to Do"));
}
public static void walkin(File dir, BufferedWriter out) throws IOException {
String pattern = ".mp4";
// BufferedWriter out = new BufferedWriter(
// new FileWriter("D:\\path.txt",true));
File listFile[] = dir.listFiles();
if (listFile != null) {
for (int i = 0; i < listFile.length; i++) {
if (listFile[i].getName().endsWith(pattern)
&& listFile[i].isFile()) {
if (filez.add(listFile[i].getPath())) {
// System.out.println(listFile[i].getPath());
out.write(listFile[i].toString());
out.write("\r\n");
// System.out.println(filez);
}
} else {
walkin(listFile[i], out);
}
}
}
}
public static void readfile() {
BufferedReader br = null;
String str;
try {
BufferedWriter out = new BufferedWriter(new FileWriter(
"D:\\duplicate_free.txt"));
br = new BufferedReader(new FileReader("D:\\path.txt"));
while ((str = br.readLine()) != null) {
if (files.contains(str)) {
} else {
files.add(str);
}
}
for (String uniq : files) {
out.write(uniq);
System.out.println(uniq);
}
out.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}

Related

Change delimiter in OpenCSV CSVReader

I have the following piece of code which reads a CSV file.
public class TestMain {
public static void parseTsv(String filePath) throws Exception {
try (CSVReader reader = new CSVReader(new InputStreamReader(Objects.requireNonNull(TestMain.class.getResourceAsStream(filePath))))) {
String[] line;
while ((line = reader.readNext()) != null) {
System.out.println(line[0] + " " + line[1]);
}
}
}
public static void main(String[] args) {
try {
parseTsv("path-to-tsv-file");
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
And I want to modify the delimiter so that it can read tsv files (tab-separated). Any help would be greatly appreciated!
With g00se's help, please see below the correct code:
public class TestMain {
public static void parseTsv(String filePath) throws Exception {
try (CSVReader reader = new CSVReaderBuilder(new InputStreamReader(Objects.requireNonNull(TestMain.class.getResourceAsStream(filePath))))
.withCSVParser(new CSVParserBuilder().withSeparator('\t').build())
.build()) {
String[] line;
while ((line = reader.readNext()) != null) {
System.out.println(line[0] + " " + line[1]);
}
}
}
public static void main(String[] args) {
try {
parseTsv("path-to-tsv-file");
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}

Proper way to use Generics in this example?

FileReader fileReader = null;
Object reader = null;
String dataRow = null;
fileReader = new FileReader(new File(fileLocation));
if (extension.equals("csv"))
{
reader = new CSVReader(fileReader);
}
else
{
reader = new BufferedReader(fileReader);
}
while (null != (dataRow = reader.readLine()))
{
...
}
The idea is to use different types depending on the file type in order to remove duplicated code. However, I get an error on the last line, since reader is type Object. Thanks for the help.
Maybe you could make 2 methods:
public String read(CSVReader c){
return c.readLine();
}
public String read(BufferedReader br){
return br.readLine();
}
Then, in your current code:
if(extension.equals("csv"))
dataRow = read(new CSVReader(fileReader));
else
dataRow = read(new BufferedReader(fileReader));
This overloading would remove the need for a wrapper class.
If you really want to use a wrapper class, I recommend having this somewhere:
public interface MyIO{
public String readLine();
}
public class MyBr extends BufferedReader implements MyIO{}
public class MyCSV extends CSVReader implements MyIO{}
Then, in your code:
MyIO reader;
if(extension.equals("csv"))
reader = new MyCSV(fileReader);
else
reader = new MyBr(fileReader);
You'd notice that both are the same number of lines of code and (in my opinion) the methods are easier to follow.
Just answering to point out that it is certainly possible to use generics even if your types are not cooperative. You'll just have to define specializations for each type separately. I'll just put a sketch in Java 8 here. Not sure what you mean by 'Proper way', there are pros and cons to everything...especially in Java.
Somewhat simpler way, putting generic code in a common superclass:
interface GenericExample {
interface InputGenericCode<Input> {
/**
* This is implemented in subtypes.
*
* #param x
* #return
*/
String readLine(Input x);
default void genericAlgorithm(Input x) {
// algorithm expressed generically here...
for (;;) {
String lineString = readLine(x);
System.out.println("" + lineString);
}
}
}
public class BufferedReaderInputGenericCode implements InputGenericCode<BufferedReader> {
#Override
public String readLine(BufferedReader x) {
try {
return x.readLine();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
public class CSVReaderInputGenericCode implements InputGenericCode<CSVReader> {
#Override
public String readLine(CSVReader x) {
return x.readLine();
}
}
static class CSVReader {
public CSVReader(FileReader fileReader) {
throw new RuntimeException("implement this");
}
public String readLine() {
throw new RuntimeException("implement this");
}
}
public static void main(String fileLocation, String extension) {
FileReader fileReader = openFile(fileLocation);
if (extension.equals("csv")) {
CSVReader reader = new CSVReader(fileReader);
new CSVReaderInputGenericCode().genericAlgorithm(reader);
} else {
BufferedReader reader = new BufferedReader(fileReader);
new BufferedReaderInputGenericCode().genericAlgorithm(reader);
}
// dataRow = reader.readLine();
}
public static FileReader openFile(String fileLocation) {
FileReader fileReader = null;
try {
fileReader = new FileReader(new File(fileLocation));
} catch (FileNotFoundException e) {
throw new RuntimeException(e);
}
return fileReader;
}
}
More complex way:
interface GenericExample {
/**
* All generic operations.
*
* #author jonasn
*
* #param <Input>
*/
interface InputGenerics<Input> {
String readLine(Input x);
}
interface InputGenericCode {
public static <Input> void genericAlgorithm(Input x, InputGenerics<Input> generics) {
// algorithm expressed generically here...
for (;;) {
String lineString = generics.readLine(x);
System.out.println("" + lineString);
}
}
}
static class CSVReader {
public CSVReader(FileReader fileReader) {
// TODO Auto-generated constructor stub
}
public String readLine() {
throw new RuntimeException("not implemented");
}
}
public class CSVReaderInputGenerics implements InputGenerics<CSVReader> {
#Override
public String readLine(CSVReader x) {
return x.readLine();
}
}
public class BufferedReaderInputGenerics implements InputGenerics<BufferedReader> {
#Override
public String readLine(BufferedReader x) {
try {
return x.readLine();
} catch (IOException e) {
// TODO Auto-generated catch block
throw new RuntimeException(e);
}
}
}
public static void main(String fileLocation, String extension) {
// String fileLocation = "whatever";
// String extension = "";
FileReader fileReader = null;
// Object reader = null;
String dataRow = null;
try {
fileReader = new FileReader(new File(fileLocation));
} catch (FileNotFoundException e) {
throw new RuntimeException(e);
}
if (extension.equals("csv"))
{
CSVReader reader = new CSVReader(fileReader);
InputGenericCode.genericAlgorithm(reader, new CSVReaderInputGenerics());
}
else
{
BufferedReader reader = new BufferedReader(fileReader);
InputGenericCode.genericAlgorithm(reader, new BufferedReaderInputGenerics());
}
// dataRow = reader.readLine();
}
}

Java run linux(raspbian) command(omxplayer) and get output

I create a program as below to execute a linux (raspbian) command: "omxplayer".
But I don't know why I cannot get output from omxplayer as the time I type it into command line and hit Enter.But the output only show at the end of the video.
So I want to get the output immediately after I type "omxplayer [video_name]" and hit "Enter" in my program.
Just like the command line (terminal) work when I type directly into it in linux.
This is my code:
public class testprog {
public static void main(String args[]) throws IOException {
String in = "";
while(in!="exit")
{
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
in = reader.readLine();
runCommand(in);
}
}
public static void runCommand(String command)
{
String s;
Process p;
try {
System.out.println("run command " + command);
p = Runtime.getRuntime().exec(new String[]{"bash", "-c",command});
MyInputStreamReader reader1 = new MyInputStreamReader(p.getInputStream());
reader1.setTag("in");
reader1.start();
MyInputStreamReader reader2 = new MyInputStreamReader(p.getErrorStream());
reader2.setTag("in");
reader2.start();
p.waitFor();
System.out.println ("exit: " + p.exitValue());
p.destroy();
} catch (Exception e) {}
}
}
class MyInputStreamReader extends Thread{
boolean isStop = false;
ReadEventHandler handler;
String tag;
InputStream in;
public MyInputStreamReader(InputStream in)
{
this.in = in;
}
public void setHandler(ReadEventHandler handler) {
this.handler = handler;
}
public void setTag(String tag)
{
this.tag = tag;
}
public void run()
{
byte[] buff = new byte[8192];
while (true) {
//String line;
try {
int len = in.read(buff);
if (len == -1)
{
return;
}
String line = new String(buff, 0, len);
if (handler!=null)
handler.onReceived(line);
System.out.println(tag +" " + line);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public void dispose()
{
this.isStop = true;
}
public interface ReadEventHandler
{
void onReceived(String line);
}
}
Any response is highly appreciated. Thanks
Did you checked this?
http://javedmandary.blogspot.com/2014/01/firing-up-raspberry-pi-omxplayer-using.html
I guess there is the code you're looking for.

Save/Load a file in android for a game

I have created a game in Android. I have written a class for input/ouput with prefer install location external. I want to make some basic questions. First of all the file I use is a .txt (I know that its not the best way to save your data but I use it for testing). The strange part is that when the the game is over it should automatically save the user highscores but it does not, so when I close the app and restart it the highscores have disappeared. I would also like to learn what the prefered file type for saving settings/highscores/coins etc (hopefully secured) is. Lastly I debug the game using a Nexus 5 whitch does not have external storage (it should be stored locally though). This is my code, thanks in advance :).
public class AndroidFileIO implements FileIO {
Context context;
AssetManager assets;
String externalStoragePath;
public AndroidFileIO(Context context) {
this.context = context;
this.assets = context.getAssets();
this.externalStoragePath = Environment.getExternalStorageDirectory()
.getAbsolutePath() + File.separator;
}
public InputStream readAsset(String fileName) throws IOException {
return assets.open(fileName);
}
public InputStream readFile(String fileName) throws IOException {
return new FileInputStream(externalStoragePath + fileName);
}
public OutputStream writeFile(String fileName) throws IOException {
return new FileOutputStream(externalStoragePath + fileName);
}
public SharedPreferences getPreferences() {
return PreferenceManager.getDefaultSharedPreferences(context);
}
}
my game class has this method
public FileIO getFileIO() {
return fileIO;
}
this is the way i load the file
Settings.load(game.getFileIO());
and finaly my save/load methods of the settings class
public static void load(FileIO files) {
BufferedReader in = null;
try {
in = new BufferedReader(new InputStreamReader(
files.readFile("mrnom.txt")));
soundEnabled = Boolean.parseBoolean(in.readLine());
for (int i = 0; i < 5; i++) {
highscores[i] = Integer.parseInt(in.readLine());
}
} catch (IOException e) {
// :( It's ok we have defaults
} catch (NumberFormatException e) {
// :/ It's ok, defaults save our day
} finally {
try {
if (in != null)
in.close();
} catch (IOException e) {
}
}
}
public static void save(FileIO files) {
BufferedWriter out = null;
try {
out = new BufferedWriter(new OutputStreamWriter(
files.writeFile("mrnom.txt")));
out.write(Boolean.toString(soundEnabled));
for (int i = 0; i < 5; i++) {
out.write(Integer.toString(highscores[i]));
}
} catch (IOException e) {
} finally {
try {
if (out != null)
out.close();
} catch (IOException e) {
}
}
}
Here save is called
private void updateGameOver(List<TouchEvent> touchEvents) {
int len = touchEvents.size();
for(int i = 0; i < len; i++) {
TouchEvent event = touchEvents.get(i);
if(event.type == TouchEvent.TOUCH_UP) {
if(event.x >= 128 && event.x <= 192 &&
event.y >= 200 && event.y <= 264) {
if(Settings.soundEnabled)
Assets.click.play(1);
//debug begin
FileIO fileIO = game.getFileIO();
Settings.save(fileIO);
//debug end
game.setScreen(new MainMenuScreen(game));
return;
}
}
}
}
Your issue is in the save method when you write the strings to the out reference. You are not saving a value per line, but are later reading a value per line in your load method. With the current code you save the following in your mrnom.txt file: true10203040 instead of true\n10\n20\n30\n40.
To fix this, one way is to change:
out.write(Boolean.toString(soundEnabled));
to
out.write(Boolean.toString(soundEnabled) + "\n");
AND
out.write(Integer.toString(highscores[i]));
to
out.write(Integer.toString(highscores[i]) + "\n");

How to filter a particular directory and copy the rest of the folders in java

I am trying to copy folders and files which is working fine but I need help on how to filter a single folder and copy the rest of the folders. For example, I have directories like carsfolder and truckfolder in(C:\vehicle\carsfolder and C:\vehicle\truckfolder). When I use the below code it copies both carsfolder and truckfolder but I wanted to copy only carsfolder. How can I do that. Your help is highly appreciated.(Using Swing and Java 1.6)
class CopyTask extends SwingWorker<Void, Integer>
{
private File source;
private File target;
private long totalBytes = 0;
private long copiedBytes = 0;
public CopyTask(File src, File dest)
{
this.source = src;
this.target = dest;
progressAll.setValue(0);
}
#Override
public Void doInBackground() throws Exception
{
ta.append("Retrieving info ... "); //append to TextArea
retrieveTotalBytes(source);
ta.append("Done!\n");
copyFiles(source, target);
return null;
}
#Override
public void process(List<Integer> chunks)
{
for(int i : chunks)
{
}
}
#Override
public void done()
{
setProgress(100);
}
private void retrieveTotalBytes(File sourceFile)
{
try
{
File[] files = sourceFile.listFiles();
for(File file : files)
{
if(file.isDirectory()) retrieveTotalBytes(file);
else totalBytes += file.length();
}
}
catch(Exception ee)
{
}
}
private void copyFiles(File sourceFile, File targetFile) throws IOException
{
if(sourceFile.isDirectory())
{
try{
if(!targetFile.exists()) targetFile.mkdirs();
String[] filePaths = sourceFile.list();
for(String filePath : filePaths)
{
File srcFile = new File(sourceFile, filePath);
File destFile = new File(targetFile, filePath);
copyFiles(srcFile, destFile);
}
}
catch(Exception ie)
{
}
}
else
{
try
{
ta.append("Copying " + sourceFile.getAbsolutePath() + " to " + targetFile.getAbsolutePath() );
bis = new BufferedInputStream(new FileInputStream(sourceFile));
bos = new BufferedOutputStream(new FileOutputStream(targetFile));
long fileBytes = sourceFile.length();
long soFar = 0;
int theByte;
while((theByte = bis.read()) != -1)
{
bos.write(theByte);
setProgress((int) (copiedBytes++ * 100 / totalBytes));
publish((int) (soFar++ * 100 / fileBytes));
}
bis.close();
bos.close();
publish(100);
ta.append(" Done!\n");
}
catch(Exception excep)
{
setProgress(0);
bos.flush();
bis.close();
bos.close();
}
finally{
try {
bos.flush();
}
catch (Exception e) {
}
try {
bis.close();
}
catch (Exception e) {
}
try {
bos.close();
}
catch (Exception e) {
}
}
}
}
}
Maybe you can introduce a regex or list of regexes that specify which files and dirs to exclude?
For example, to exclude truckfolder, use a "exclusion" regex like "C:\\vehicle\\truckfolder.*".
Then, in your code, before you copy anything, check to make sure the absolute path of the sourcefile doesn't match the exclusion regex(s).

Categories