Appending characters onto string - java

I am trying to write code to import all characters (including spaces) of a given text file into a single string for analysis. I am using the given files in Java for this, and ran across a strange error while putthing it together. I'm not really familiar with coding at all, and would appreciate clarification. What happens is that in the below code, when I set
text.append(ch);
I have errors of Default constructor cannot handle exception thrown by X, must define explicit constructor;
and when I set text.append('ch');
the above errors go away and my 'ch' line just gives invalid char const. error, fixable by removing the ''s.
So I take it I have to construct an explicit constructor for my givens from Java, is this necessary? As I have no idea how to do so, it would be nice to have a roundabout solution.
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.lang.StringBuilder;
public class TextReader //cannot place inputs/outputs of string on this line
{
StringBuilder text = new StringBuilder();
//StringBuilder google
//google end of file check java
InputStream in = new FileInputStream("charfile.txt");
Reader r = new InputStreamReader(in, "US-ASCII");
int intch;
{
while ((intch = r.read()) != -1)
{
char ch = (char) intch;
// ...
text.append(ch); //if I make this a 'ch', the errors above go away, what's the problem?
}
}
}

You need to place your statements in a code block, e.g. main method.
public static void main(String[] args) throws IOException {
StringBuilder text = new StringBuilder();
// StringBuilder google
// google end of file check java
InputStream in = new FileInputStream("charfile.txt");
Reader r = new InputStreamReader(in, "US-ASCII");
int intch;
{
while ((intch = r.read()) != -1) {
char ch = (char) intch;
// ...
text.append(ch);
}
}
}
The statements
InputStream in = new FileInputStream("charfile.txt");
Reader r = new InputStreamReader(in, "US-ASCII");
both throw checked exceptions which cannot occur in the class block.

Actually IO in java require try and catch block, else it will give you error. Also in above code you have to place the declaration in explicitly define constructor
TextReader()
{
//----------- Your Code here.
}

When you do text.append(ch);, error should not come at this line. It may complain about other issue e.g. Expected Exceptions not handled or thrown e.g.
Handled:
try{
while ((intch = r.read()) != -1){
char ch = (char) intch;
// ...
text.append(ch);
}
}catch(IOException ioex){
ioex.printStackTace();
}
Thrown:
Change your method declaration with throws clause as :
public static void main(String[] args) throws IOException{
When you say text.append('ch');, your argument is not a variable or single character literal any more. You should be getting compilation error at that line. Though you can do something like text.append('c'); as c is a single character.

Related

How to gets numbers from txt file and than parse to integer?

I use Android Studio.I have a text file with some of numbers and I want to calculate them with others numbers. When I am try to convert them from string with method Integer.parseInt on program start I get error and program close.Error is :
at java.lang.Integer.parseInt(Integer.java:521)
at java.lang.Integer.parseInt(Integer.java:556)
I am just beginner and sorry for bad english , I hope you understand my problem.
This is part of my code.
public void read (){
try {
FileInputStream fileInput = openFileInput("example.txt");
InputStreamReader reader = new InputStreamReader(fileInput);
BufferedReader buffer = new BufferedReader(reader);
StringBuffer strBuffer = new StringBuffer();
String lines;
while ((lines = buffer.readLine()) != null) {
strBuffer.append(lines + "\n");
}
int numbers = Integer.parseInt(strBuffer.toString());
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
Here:
int numbers = Integer.parseInt(strBuffer.toString());
You should read the javadoc for the library methods you are using. parseInt() parses one number from a string that contains one number.
So you need
to learn how to use arrays of int (because you want to read and process multiple numbers), not just a single one
to then use parseInt() on the individual number strings in that file
Also note that you can use the Scanner to directly work on an InputStream, there is no need to first turn the complete file content into one large string in memory!
Integer.parseInt(String) throws a NumberFormatException when its argument can't be converted to a number.
Break your problem into smaller, more manageable blocks. Your code currently gets the entire content of example.txt and tries to parse the whole thing to an Integer.
One possibility for reading all integer values is to do this with a java.util.Scanner object instead and use its nextInt() method.
Consider the following example, given a file example.txt with integers separated by spaces.
import java.io.File;
import java.io.InputStream;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
public class App {
public static void main(String...args) throws Exception {
File file = new File("/home/william/example.txt");
try (InputStream is = Files.newInputStream(file.toPath())) {
Scanner scanner = new Scanner(is);
List<Integer> ints = new ArrayList<>();
while (scanner.hasNextInt()) {
int i = scanner.nextInt();
System.out.printf("Read %d%n", i);
ints.add(i);
}
}
}
}

Hex Viewer in Java

I'm a beginner in java programming and i'm trying to create a hex viewer in java, my IDE is Netbeans. Below is the code.
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import static java.lang.System.out;
import javax.swing.JFileChooser;
public class hope {
public static void main(String[] args) throws IOException {
JFileChooser open = new JFileChooser();
open.showOpenDialog(null);
File f = open.getSelectedFile();
InputStream is = new FileInputStream(f);
int bytesCounter = 0;
int value = 0;
StringBuilder sbHex = new StringBuilder();
StringBuilder sbResult = new StringBuilder();
while ((value = is.read()) != -1) {
//convert to hex value with "X" formatter
sbHex.append(String.format("%02X ", value));
//if 16 bytes are read, reset the counter,
//clear the StringBuilder for formatting purpose only.
if (bytesCounter == 15) {
sbResult.append(sbHex).append("\n");
sbHex.setLength(0);
bytesCounter = 0;
} else {
bytesCounter++;
}
}
//if still got content
if (bytesCounter != 0) {
//add spaces more formatting purpose only
for (; bytesCounter < 16; bytesCounter++) {
//1 character 3 spaces
sbHex.append(" ");
}
sbResult.append(sbHex).append("\n");
}
out.print(sbResult);
is.close();
}
}
The problem are:
1. It doesn't read the files fast enough"It takes a minute to read a file of 200kb"
2. It gives "Out of Memory" error when I tried a large file e.g. 80mb
What I want it to do:
1. Display all the hex code in seconds "Read and display hex of any size of file"
2. read file of any size without error code.
The Question:
What do I need to change or add in my code to achieve the above "What I want it to do"?
For this simple example, the key is to use "Buffered" input stream.
Change this line of code:
InputStream is = new FileInputStream(f);
to:
InputStream is = new BufferedInputStream( new FileInputStream(f));
You will get a much better result.
(But to fix the Out of Memory error, you have to think about a different approach since currently you are "caching" all the data to one string which will eat all your memory. Maybe print/clear the string builder each time the counter reaches 15 or higher? You can try and let us know. :)

How can I parse through a file for a string matching a generated string?

My bad for the title, I am usually not good at making those.
I have a programme that will generate all permutations of an inputted word and that is supposed to check to see if those are words (checks dictionary), and output the ones that are. Really I just need the last the part and I can not figure out how to parse through a file.
I took out what was there (now displaying the "String words =") because it really made thing worse (was an if statement). Right now, all it will do is output all permutations.
Edit: I should add that the try/catch was added in when I tried turning the file in a list (as opposed to the string format which it is currently in). So right now it does nothing.
One more thing: is it possible (well how, really) to get the permutations to display permutations with lesser characters than entered ? Sorry for the bad wording, like if I enter five characters, show all five character permutations, and four, and three, and two, and one.
import java.util.List;
import java.util.Scanner;
import java.io.BufferedReader;
import java.io.File;
import java.io.InputStreamReader;
import java.io.IOException;
import org.apache.commons.io.FileUtils;
import static java.lang.System.out;
public class Permutations
{
public static void main(String[] args) throws Exception
{
out.println("Enter anything to get permutations: ");
Scanner scan = new Scanner(System.in);
String io = scan.nextLine();
String str = io;
StringBuffer strBuf = new StringBuffer(str);
mutate(strBuf,str.length());
}
private static void mutate(StringBuffer str, int index)
{
try
{
String words = FileUtils.readFileToString(new File("wordsEn.txt"));
if(index <= 0)
{
out.println(str);
}
else
{
mutate(str, index - 1);
int currLoc = str.length()-index;
for (int i = currLoc + 1; i < str.length(); i++)
{
change(str, currLoc, i);
mutate(str, index - 1);
change(str, i, currLoc);
}
}
}
catch(IOException e)
{
out.println("Your search found no results");
}
}
private static void change(StringBuffer str, int loc1, int loc2)
{
char t1 = str.charAt(loc1);
str.setCharAt(loc1, str.charAt(loc2));
str.setCharAt(loc2, t1);
}
}
If each word in your file is actually on a different line, maybe you can try this:
BufferedReader br = new BufferedReader(new FileReader(file));
String line = null;
while ((line = br.readLine()) != null)
{
... // check and print here
}
Or if you want to try something else, the Apache Commons IO library has something called LineIterator.
An Iterator over the lines in a Reader.
LineIterator holds a reference to an open Reader. When you have finished with the iterator you should close the reader to free internal resources. This can be done by closing the reader directly, or by calling the close() or closeQuietly(LineIterator) method on the iterator.
The recommended usage pattern is:
LineIterator it = FileUtils.lineIterator(file, "UTF-8");
try {
while (it.hasNext()) {
String line = it.nextLine();
// do something with line
}
} finally {
it.close();
}

Basic Java IO, always throwing exception

I'm new to Java and am trying to write a program that has one argument, the path of a text file. The program will locate the text file and print it out to the screen. Eventually I'm going to build this to format the given text file and then print it out to an outfile, but I'll get there later.
Anyways my program is always throwing and IOException and I'm not sure why. Given the argument C:\JavaUtility\input.txt , I receieve "Error, could not read file" during runtime. My code is located below.
import java.io.*;
public class utility {
public static void main(String[] path){
try{
FileReader fr = new FileReader(path[0]);
BufferedReader textReader = new BufferedReader(fr);
String aLine;
int numberOfLines = 0;
while ((aLine = textReader.readLine()) != null) {
numberOfLines++;
}
String[] textData = new String[numberOfLines];
for (int i=0;i < numberOfLines; i++){
textData[i] = textReader.readLine();
}
System.out.println(textData);
return;
}
catch(IOException e){
System.out.println("Error, could not read file");
}
}
}
[EDIT] Thanks for all the help everyone! So given my end goal, I thought it would still be useful to find the number of lines and store in a finite array. So I ended up writing two classes. The first, ReadFile.java found the data I wanted and handles most of the reading. The second FileData.java invokes the methods in ReadFile and prints out. I've posted them below incase someone later finds them useful.
package textfiles;
import java.io.*;
public class ReadFile {
private String path;
public ReadFile(String file_path){
path = file_path;
}
int readLines() throws IOException{
FileReader file_to_read = new FileReader(path);
BufferedReader bf = new BufferedReader(file_to_read);
String aLine;
int numberOfLines = 0;
while ((aLine = bf.readLine()) != null){
numberOfLines++;
}
bf.close();
return numberOfLines;
}
public String[] OpenFile() throws IOException{
FileReader fr = new FileReader(path);
BufferedReader textReader = new BufferedReader(fr);
int numberOfLines = readLines();
String[] textData = new String[numberOfLines];
for(int i=0; i < numberOfLines; i++){
textData[i] = textReader.readLine();
}
textReader.close();
return textData;
}
}
package textfiles;
import java.io.IOException;
public class FileData {
public static void main(String[] args)throws IOException{
String file_name = args[0];
try{
ReadFile file = new ReadFile(file_name);
String[] aryLines = file.OpenFile();
for(int i=0; i < aryLines.length; i++){
System.out.println(aryLines[i]);
}
}
catch (IOException e){
System.out.println(e.getMessage());
}
}
}
You're at the end of the file. When you determine the number of lines in the file, you've read until the end of the file,and the EOF Flag is set. [Edit: As #EJP notes below, BufferedReader returns null reading past the end of a file. The fact your reader isn't where you want it, however, remains true.] In the past, I've hacked around this simply by closing and re-opening the file. Alternatively, look into Array Lists or simple Lists. They're dynamically re-sizing, so you don't need to know the number of lines in the file ahead of time.
As mentioned by #mikeTheLiar you are at End Of File. BufferedReader reference is File Handler with an internal cursor pointing to current position in file. As you fire readLine() method, the pointer reads characters till it reaches new line character, returning the string. The pointer is set to new position. Once you read all the lines then readLine() returns null. After that if you call readLine() it will throw IOException. As noted by #EJP
One of the best coding rules while using IO API is to always check for EOF condition - the way you have in first loop. Once you reach EOF after that you should not call read method on the same reference without resetting the cursor - this can be done by calling reset() method.
IMHO, in your case there is no need for second loop. You can achieve the functionalty using one loop only.
import java.io.*;
import java.util.ArrayList;
public class utility {
public static void main(String[] path){
try{
FileReader fr = new FileReader(path[0]);
BufferedReader textReader = new BufferedReader(fr);
String aLine;
int numberOfLines = 0;
ArrayList readLines = new ArrayList();
while ((aLine = textReader.readLine()) != null) {
numberOfLines++;
readLines.add(aLine);
}
//Assuming you need array of lines, if not then you can print the lines directly in above loop
String[] textData = readLines.toArray();
System.out.println(textData);
return;
}
catch(IOException e){
System.out.println("Error, could not read file");
}
}
}
EDIT
I tried your code - it is working fine and printing the array reference. As suggested in comments the problem is with source (file might not be readable due to security or any other reason) - if you can print the exception message and get the exact line number where exception is thrown it would be helpful.
Couple of observations apart from the IO exception:
You are trying to open the file twice. readLines() method is called from within OpenFile(). Following the sequence of code file is first opened in OpenFile() when you create textReader. After that you are calling readLines() which is again trying to open the file when you create file_to_read.
You should try to avoid that and in your flow you should call int numberOfLines = readLines(); before FileReader fr = new FileReader(path);
Again IMHO there should be only one method and you should iterate over the file only once - both from efficience/performance and code maintainability perspective. You can change your ReadFile class as follows:
package textfiles;
import java.io.*;
import java.util.ArrayList;
public class ReadFile {
private String path;
public ReadFile(String file_path){
path = file_path;
}
//You need not have separate file for counting lines in file
//Java provides dynamic sized arrays using ArrayList
//There is no need to count lines
public String[] OpenFile() throws IOException{
FileReader fr = new FileReader(path);
BufferedReader textReader = new BufferedReader(fr);
ArrayList fileLines = new ArrayList();
String readLine = textReader.readLine();
while(readLine != null){
fileLines.add(readLine);
readLine = textReader.readLine();
}
textReader.close();
return fileLines.toArray();
}
}
Another small observation: in some places the java variable naming conventions are not followed. OpenFile() method should be openFile() and file_to_read should be fileToRead
Contrary to several answers here, readLine() does not throw an exception at end of file, it just keeps returning null. Your problem is being masked by another one. Never just make up your own error messages. Always print the one that comes with the exception. If you had done that you would probably have found the problem immediately. Almost certainly you weren't able to open the file at all, either because it wasn't there or you didn't have read access. The exception will tell you.

Read a file line by line in reverse order

I have a java ee application where I use a servlet to print a log file created with log4j. When reading log files you are usually looking for the last log line and therefore the servlet would be much more useful if it printed the log file in reverse order. My actual code is:
response.setContentType("text");
PrintWriter out = response.getWriter();
try {
FileReader logReader = new FileReader("logfile.log");
try {
BufferedReader buffer = new BufferedReader(logReader);
for (String line = buffer.readLine(); line != null; line = buffer.readLine()) {
out.println(line);
}
} finally {
logReader.close();
}
} finally {
out.close();
}
The implementations I've found in the internet involve using a StringBuffer and loading all the file before printing, isn't there a code light way of seeking to the end of the file and reading the content till the start of the file?
[EDIT]
By request, I am prepending this answer with the sentiment of a later comment: If you need this behavior frequently, a "more appropriate" solution is probably to move your logs from text files to database tables with DBAppender (part of log4j 2). Then you could simply query for latest entries.
[/EDIT]
I would probably approach this slightly differently than the answers listed.
(1) Create a subclass of Writer that writes the encoded bytes of each character in reverse order:
public class ReverseOutputStreamWriter extends Writer {
private OutputStream out;
private Charset encoding;
public ReverseOutputStreamWriter(OutputStream out, Charset encoding) {
this.out = out;
this.encoding = encoding;
}
public void write(int ch) throws IOException {
byte[] buffer = this.encoding.encode(String.valueOf(ch)).array();
// write the bytes in reverse order to this.out
}
// other overloaded methods
}
(2) Create a subclass of log4j WriterAppender whose createWriter method would be overridden to create an instance of ReverseOutputStreamWriter.
(3) Create a subclass of log4j Layout whose format method returns the log string in reverse character order:
public class ReversePatternLayout extends PatternLayout {
// constructors
public String format(LoggingEvent event) {
return new StringBuilder(super.format(event)).reverse().toString();
}
}
(4) Modify my logging configuration file to send log messages to both the "normal" log file and a "reverse" log file. The "reverse" log file would contain the same log messages as the "normal" log file, but each message would be written backwards. (Note that the encoding of the "reverse" log file would not necessarily conform to UTF-8, or even any character encoding.)
(5) Create a subclass of InputStream that wraps an instance of RandomAccessFile in order to read the bytes of a file in reverse order:
public class ReverseFileInputStream extends InputStream {
private RandomAccessFile in;
private byte[] buffer;
// The index of the next byte to read.
private int bufferIndex;
public ReverseFileInputStream(File file) {
this.in = new RandomAccessFile(File, "r");
this.buffer = new byte[4096];
this.bufferIndex = this.buffer.length;
this.in.seek(file.length());
}
public void populateBuffer() throws IOException {
// record the old position
// seek to a new, previous position
// read from the new position to the old position into the buffer
// reverse the buffer
}
public int read() throws IOException {
if (this.bufferIndex == this.buffer.length) {
populateBuffer();
if (this.bufferIndex == this.buffer.length) {
return -1;
}
}
return this.buffer[this.bufferIndex++];
}
// other overridden methods
}
Now if I want to read the entries of the "normal" log file in reverse order, I just need to create an instance of ReverseFileInputStream, giving it the "revere" log file.
This is a old question. I also wanted to do the same thing and after some searching found there is a class in apache commons-io to achieve this:
org.apache.commons.io.input.ReversedLinesFileReader
I think a good choice for this would be using RandomFileAccess class. There is some sample code for back-reading using this class on this page. Reading bytes this way is easy, however reading strings might be a bit more challenging.
If you are in a hurry and want the simplest solution without worrying too much about performance, I would give a try to use an external process to do the dirty job (given that you are running your app in a Un*x server, as any decent person would do XD)
new BufferedReader(new InputStreamReader(Runtime.getRuntime().exec("tail yourlogfile.txt -n 50 | rev").getProcess().getInputStream()))
A simpler alternative, because you say that you're creating a servlet to do this, is to use a LinkedList to hold the last N lines (where N might be a servlet parameter). When the list size exceeds N, you call removeFirst().
From a user experience perspective, this is probably the best solution. As you note, the most recent lines are the most important. Not being overwhelmed with information is also very important.
Good question. I'm not aware of any common implementations of this. It's not trivial to do properly either, so be careful what you choose. It should deal with character set encoding and detection of different line break methods. Here's the implementation I have so far that works with ASCII and UTF-8 encoded files, including a test case for UTF-8. It does not work with UTF-16LE or UTF-16BE encoded files.
import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.RandomAccessFile;
import java.io.Reader;
import java.io.UnsupportedEncodingException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import junit.framework.TestCase;
public class ReverseLineReader {
private static final int BUFFER_SIZE = 8192;
private final FileChannel channel;
private final String encoding;
private long filePos;
private ByteBuffer buf;
private int bufPos;
private byte lastLineBreak = '\n';
private ByteArrayOutputStream baos = new ByteArrayOutputStream();
public ReverseLineReader(File file, String encoding) throws IOException {
RandomAccessFile raf = new RandomAccessFile(file, "r");
channel = raf.getChannel();
filePos = raf.length();
this.encoding = encoding;
}
public String readLine() throws IOException {
while (true) {
if (bufPos < 0) {
if (filePos == 0) {
if (baos == null) {
return null;
}
String line = bufToString();
baos = null;
return line;
}
long start = Math.max(filePos - BUFFER_SIZE, 0);
long end = filePos;
long len = end - start;
buf = channel.map(FileChannel.MapMode.READ_ONLY, start, len);
bufPos = (int) len;
filePos = start;
}
while (bufPos-- > 0) {
byte c = buf.get(bufPos);
if (c == '\r' || c == '\n') {
if (c != lastLineBreak) {
lastLineBreak = c;
continue;
}
lastLineBreak = c;
return bufToString();
}
baos.write(c);
}
}
}
private String bufToString() throws UnsupportedEncodingException {
if (baos.size() == 0) {
return "";
}
byte[] bytes = baos.toByteArray();
for (int i = 0; i < bytes.length / 2; i++) {
byte t = bytes[i];
bytes[i] = bytes[bytes.length - i - 1];
bytes[bytes.length - i - 1] = t;
}
baos.reset();
return new String(bytes, encoding);
}
public static void main(String[] args) throws IOException {
File file = new File("my.log");
ReverseLineReader reader = new ReverseLineReader(file, "UTF-8");
String line;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
}
public static class ReverseLineReaderTest extends TestCase {
public void test() throws IOException {
File file = new File("utf8test.log");
String encoding = "UTF-8";
FileInputStream fileIn = new FileInputStream(file);
Reader fileReader = new InputStreamReader(fileIn, encoding);
BufferedReader bufReader = new BufferedReader(fileReader);
List<String> lines = new ArrayList<String>();
String line;
while ((line = bufReader.readLine()) != null) {
lines.add(line);
}
Collections.reverse(lines);
ReverseLineReader reader = new ReverseLineReader(file, encoding);
int pos = 0;
while ((line = reader.readLine()) != null) {
assertEquals(lines.get(pos++), line);
}
assertEquals(lines.size(), pos);
}
}
}
you can use RandomAccessFile implements this function,such as:
import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import com.google.common.io.LineProcessor;
public class FileUtils {
/**
* 反向读取文本文件(UTF8),文本文件分行是通过\r\n
*
* #param <T>
* #param file
* #param step 反向寻找的步长
* #param lineprocessor
* #throws IOException
*/
public static <T> T backWardsRead(File file, int step,
LineProcessor<T> lineprocessor) throws IOException {
RandomAccessFile rf = new RandomAccessFile(file, "r");
long fileLen = rf.length();
long pos = fileLen - step;
// 寻找倒序的第一行:\r
while (true) {
if (pos < 0) {
// 处理第一行
rf.seek(0);
lineprocessor.processLine(rf.readLine());
return lineprocessor.getResult();
}
rf.seek(pos);
char c = (char) rf.readByte();
while (c != '\r') {
c = (char) rf.readByte();
}
rf.readByte();//read '\n'
pos = rf.getFilePointer();
if (!lineprocessor.processLine(rf.readLine())) {
return lineprocessor.getResult();
}
pos -= step;
}
}
use:
FileUtils.backWardsRead(new File("H:/usersfavs.csv"), 40,
new LineProcessor<Void>() {
//TODO implements method
.......
});
The simplest solution is to read through the file in forward order, using an ArrayList<Long> to hold the byte offset of each log record. You'll need to use something like Jakarta Commons CountingInputStream to retrieve the position of each record, and will need to carefully organize your buffers to ensure that it returns the proper values:
FileInputStream fis = // .. logfile
BufferedInputStream bis = new BufferedInputStream(fis);
CountingInputStream cis = new CountingInputSteam(bis);
InputStreamReader isr = new InputStreamReader(cis, "UTF-8");
And you probably won't be able to use a BufferedReader, because it will attempt to read-ahead and throw off the count (but reading a character at a time won't be a performance problem, because you're buffering lower in the stack).
To write the file, you iterate the list backwards and use a RandomAccessFile. There is a bit of a trick: to properly decode the bytes (assuming a multi-byte encoding), you will need to read the bytes corresponding to an entry, and then apply a decoding to it. The list, however, will give you the start and end position of the bytes.
One big benefit to this approach, versus simply printing the lines in reverse order, is that you won't damage multi-line log messages (such as exceptions).
import java.io.File;
import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
/**
* Inside of C:\\temp\\vaquar.txt we have following content
* vaquar khan is working into Citi He is good good programmer programmer trust me
* #author vaquar.khan#gmail.com
*
*/
public class ReadFileAndDisplayResultsinReverse {
public static void main(String[] args) {
try {
// read data from file
Object[] wordList = ReadFile();
System.out.println("File data=" + wordList);
//
Set<String> uniquWordList = null;
for (Object text : wordList) {
System.out.println((String) text);
List<String> tokens = Arrays.asList(text.toString().split("\\s+"));
System.out.println("tokens" + tokens);
uniquWordList = new HashSet<String>(tokens);
// If multiple line then code into same loop
}
System.out.println("uniquWordList" + uniquWordList);
Comparator<String> wordComp= new Comparator<String>() {
#Override
public int compare(String o1, String o2) {
if(o1==null && o2 ==null) return 0;
if(o1==null ) return o2.length()-0;
if(o2 ==null) return o1.length()-0;
//
return o2.length()-o1.length();
}
};
List<String> fs=new ArrayList<String>(uniquWordList);
Collections.sort(fs,wordComp);
System.out.println("uniquWordList" + fs);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
static Object[] ReadFile() throws IOException {
List<String> list = Files.readAllLines(new File("C:\\temp\\vaquar.txt").toPath(), Charset.defaultCharset());
return list.toArray();
}
}
Output:
[Vaquar khan is working into Citi He is good good programmer programmer trust me
tokens[vaquar, khan, is, working, into, Citi, He, is, good, good, programmer, programmer, trust, me]
uniquWordList[trust, vaquar, programmer, is, good, into, khan, me, working, Citi, He]
uniquWordList[programmer, working, vaquar, trust, good, into, khan, Citi, is, me, He]
If you want to Sort A to Z then write one more comparater
Concise solution using Java 7 Autoclosables and Java 8 Streams :
try (Stream<String> logStream = Files.lines(Paths.get("C:\\logfile.log"))) {
logStream
.sorted(Comparator.reverseOrder())
.limit(10) // last 10 lines
.forEach(System.out::println);
}
Big drawback: only works when lines are strictly in natural order, like log files prefixed with timestamps but without exceptions

Categories