Hi I'm reading file (please, use the link to see the file) that contains this rows:
U+0000
U+0001
U+0002
U+0003
U+0004
U+0005
using this code
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
public class fgenerator {
public static void main(String[] args) {
try(BufferedReader br = new BufferedReader(new FileReader(new File("C:\\UNCDUNCD.txt")))){
String line;
String[] splited;
while ((line = br.readLine()) != null){
splited = line.split(" ");
System.out.println(splited[0]);
}
}catch(Exception e) {
e.printStackTrace();
}
}
}
but output is
U+D01C
U+D01D
U+D01E
U+D01F
U+D020
U+D021
why does this happen?
how to get the char of its code
change line datatype to char, if doesnt work then String.getBytes()
I am assuming that you want to take the Unicode representation that is on each line of the file and output the actual Unicode character which the code represents.
If we start with your loop that reads each line from the file...
while ((line = br.readLine()) != null){
System.out.println( line );
}
... then what we want to do is convert the input line to the character, and print that ...
while ((line = br.readLine()) != null){
System.out.println( convert(line) ); <- I just put a method call to "convert()"
}
So, how do you convert(line) into a character before printing it?
As my earlier comment suggested, you want to take the numeric string that follows the U+ and convert it to an actual numeric value. That, then, is the character value you want to print.
The following is a complete program — essentially like yours but I take the filename as an argument rather than hard-coding it. I've also added skipping blank lines, and rejecting invalid strings -- printing a blank space instead.
Reject the line if it does not match the U+nnnn form of a Unicode representation — match against "(?i)U\\+[0-9A-F]{4}", which means:
(?i) - ignore case
U\\+ - match U+, where the + has to be escaped to be a literal plus
[0-9A-F] - match any character 0-9 or A-F (ignoring case)
{4} - exactly 4 times
With your update that includes a linked sample file, which includes # comments, I have modified my original program (below) so it will now strip comments and then convert the remaining representation.
This is a complete program that can be run as:
javac Reader2.java
java Reader2 inputfile.txt
I tested it with a subset of your file, starting inputfile.txt at line 1 with U+0000 and ending at line 312 with U+0138
import java.io.*;
public class Reader2
{
public static void main(String... args)
{
final String filename = args[0];
try (BufferedReader br = new BufferedReader(
new FileReader(new File( filename ))
)
)
{
String line;
while ((line = br.readLine()) != null) {
if (line.trim().length() > 0) { // skip blank lines
//System.out.println( convert(line) );
final Character c = convert(line);
if (Character.isValidCodePoint(c)) {
System.out.print ( c );
}
}
}
System.out.println();
}
catch(Exception e) {
e.printStackTrace();
}
}
private static char convert(final String input)
{
//System.out.println("Working on line: " + input);
if (! input.matches("(?i)U\\+[0-9A-F]{4}(\\s+#.*)")) {
System.err.println("Rejecting line: " + input);
return ' ';
}
else {
//System.out.println("Accepting line: " + input);
}
// else
final String stripped = input.replaceFirst("\\s+#.*$", "");
final Integer cval = Integer.parseInt(stripped.substring(2), 16);
//System.out.println("cval = " + cval);
return (char) cval.intValue();
}
}
Original program that assumed a line consisted only of U+nnnn is here.
You would run this as:
javac Reader.java
java Reader input.txt
import java.io.*;
public class Reader
{
public static void main(String... args)
{
final String filename = args[0];
try (BufferedReader br = new BufferedReader(
new FileReader(new File( filename ))
)
)
{
String line;
while ((line = br.readLine()) != null) {
if (line.trim().length() > 0) { // skip blank lines
//System.out.println( line );
// Write all chars on one line rather than one char per line
System.out.print ( convert(line) );
}
}
System.out.println(); // Print a newline after all chars are printed
}
catch(Exception e) { // don't catch plain `Exception` IRL
e.printStackTrace(); // don't just print a stack trace IRL
}
}
private static char convert(final String input)
{
// Reject any line that doesn't match U+nnnn
if (! input.matches("(?i)U\\+[0-9A-F]{4}")) {
System.err.println("Rejecting line: " + input);
return ' ';
}
// else convert the line to the character
final Integer cval = Integer.parseInt(input.substring(2), 16);
//System.out.println("cval = " + cval);
return (char) cval.intValue();
}
}
Try it using this as your input file:
U+0041
bad line
U+2718
U+00E9
u+0073
Redirect standard error when you run it java Reader input.txt 2> /dev/null or comment out the line System.err.println...
You should get this output: A ✘és
Related
I am working on a game, and I want to use this text file of mythological names to procedurally generate galaxy solar-system names.
When I read the text file, I tell the while-loop I'm using to continue if there is something that's not a name on a given line. That seems to throw an exception in some (not all) areas where there are multiple lines without names.
How can I make the program work without throwing exceptions or reading lines without names on them?
My Code:
public class Rewrite {
public static void main(String[] args) {
loadFromFile();
}
private static void loadFromFile() {
String[] names = new String[1000];
try {
FileReader fr = new FileReader("src/res/names/Galaxy_System_Names.txt");
BufferedReader br = new BufferedReader(fr);
String aLine;
int countIndex = 0;
while ((aLine = br.readLine()) != null) {
// skip lines without names
if (aLine.equals(String.valueOf(System.lineSeparator()))) {
aLine = br.readLine();
continue;
} else if (aLine.equals("&")) {
aLine = br.readLine();
continue;
} else if (aLine.startsWith("(")) {
aLine = br.readLine();
continue;
}
System.out.println(aLine);
// capitalize first letter of the line
String firstLetter = String.valueOf(aLine.charAt(0));
aLine = firstLetter + aLine.substring(1);
names[countIndex++] = aLine;
}
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
The Exception Thrown:
Exception in thread "main" java.lang.StringIndexOutOfBoundsException: String index out of range: 0
at java.base/java.lang.StringLatin1.charAt(StringLatin1.java:47)
at java.base/java.lang.String.charAt(String.java:702)
at utilities.Rewrite.loadHumanNamesFromFile(Rewrite.java:39)
at utilities.Rewrite.main(Rewrite.java:10)
Text-File sample: This throws an error after the name "amor"
áed
áedán
aegle
aella
aeneas
aeolus
aeron
(2)
&
aeson
agamemnon
agaue
aglaea
aglaia
agni
(1)
agrona
ahriman
ahti
ahura
mazda
aias
aigle
ailill
aineias
aino
aiolos
ajax
akantha
alberic
alberich
alcides
alcippe
alcmene
alcyone
alecto
alekto
alexander
alexandra
alexandros
alf
(1)
alfr
alkeides
alkippe
alkmene
alkyone
althea
alvis
alvíss
amalthea
amaterasu
amen
ameretat
amirani
ammon
amon
amon-ra
amor
&
amordad
amulius
amun
From the docs of the BufferedReader::readLine:
Returns: A String containing the contents of the line, not including any line-termination characters
Thus when you get to this part of the file:
amor
&
It will read the blank line and strip the linebreak character, and all that will be left is an empty String. Therefore it will not be caught by your if statement:
if (aLine.equals(String.valueOf(System.lineSeparator())))
You need to add in a check for isEmpty()
After amor is an empty line. You're trying to get the char at index 0 of an empty line. Since it's an empty line, it obviously has no chars, and as such there's no char at index 0
I have the following Text:
1
(some text)
/
2
(some text)
/
.
.
/
8519
(some text)
and I want to split this text into several text-files where each file has the name of the number before the text i.e. (1.txt, 2.txt) and so on, and the content of this file will be the text.
I tried this code
BufferedReader br = new BufferedReader(new FileReader("(Path)\\doc.txt"));
try {
StringBuilder sb = new StringBuilder();
String line = br.readLine();
while (line != null) {
sb.append(line);
// sb.append(System.lineSeparator());
line = br.readLine();
}
String str = sb.toString();
String[] arrOfStr = str.split("/");
for (int i = 0; i < arrOfStr.length; i++) {
PrintWriter writer = new PrintWriter("(Path)" + arrOfStr[i].charAt(0) + ".txt", "UTF-8");
writer.println(arrOfStr[i].substring(1));
writer.close();
}
System.out.println("Done");
} finally {
br.close();
}
this code works for files 1-9. However, things go wrong for files 10-8519 since I took the first number in the string (arrOfStr [i].charAt(0)) I know my solution is insufficient any suggestions?
In addition to my comment, considering there isn't a space between the leading integer and the first word, the substring at the first space doesn't work.
This question/answer has a few options that should help, the one using regex (\d+) being the simplest one imo, and copied below.
Matcher matcher = Pattern.compile("\\d+").matcher(arrOfStr[i]);
matcher.find();
int yourNumber = Integer.valueOf(matcher.group());
Given a string find the first embedded occurrence of an integer
As you mentioned, the problem is that you only take the first digit. You could enumerate the first characters until you find a non digit character ( arrOfStr[i].charAt(j) <'0' || arrOfStr[i].charAt(j) > '9' ) but it shoud be easier to user a Scanner and an appropriate regexp.
int index = new Scanner(arrOfStr[i]).useDelimiter("\\D+").nextInt();
The delimiter is precisely any group of non-digit character
Here is a quick solution for the given problem. You can test and do proper exception handling.
package practice;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.util.List;
public class FileNioTest {
public static void main(String[] args) {
Path path = Paths.get("C:/Temp/readme.txt");
try {
List<String> contents = Files.readAllLines(path);
StringBuffer sb = new StringBuffer();
String folderName = "C:/Temp/";
String fileName = null;
String previousFileName = null;
// Read from the stream
for (String content : contents) {// for each line of content in contents
if (content.matches("-?\\d+")) { // check if it is a number (based on your requirement)
fileName = folderName + content + ".txt"; // create a file name with path
if (sb != null && sb.length() > 0) { // this means if content present to write in the file
writeToFile(previousFileName, sb); // write to file
sb.setLength(0); // clearing buffer
}
createFile(fileName); // create a new file if number found in the line
previousFileName = fileName; // store the name to write content in previous opened file.
} else {
sb.append(content); // keep storing the content to write in the file.
}
System.out.println(content);// print the line
}
if (sb != null && sb.length() > 0) {
writeToFile(fileName, sb);
sb.setLength(0);
}
} catch (IOException ex) {
ex.printStackTrace();// handle exception here
}
}
private static void createFile (String fileName) {
Path newFilePath = Paths.get(fileName);
if (!Files.exists(newFilePath)) {
try {
Files.createFile(newFilePath);
} catch (IOException e) {
System.err.println(e);
}
}
}
private static void writeToFile (String fileName, StringBuffer sb) {
try {
Files.write(Paths.get(fileName), sb.toString().getBytes(), StandardOpenOption.APPEND);
}catch (IOException e) {
System.err.println(e);
}
}
}
When i read java file as tokens and print it's content,
using BufferedReader and StringTokenizer,how can i print only its content without comment statements that begin with " // " , " /* */" .
I want to print content of file without these statement that used for clarify the code.
You can do that very easily using JavaParser: just parse the code specifying that you want to ignore comments and then dump the AST
CompilationUnit cu = JavaParser.parse(reader, false /*considerComments*/);
String codeWithoutComments = cu.toString();
While dumping it will reformat the code.
1 If you want to remove comments, you can well:
remove // => see the same question here, no need of regex : Find single line comments in byte array
remove /* */ it is more difficult. regex could work, but you could get a lot of pain . I dont recommend that
2 use a java parser : Java : parse java source code, extract methods
javaparser for example: https://github.com/javaparser/javaparser
then iterate the code, and remove comments, etc.
This code will remove the comment inside a text file.But, It will not remove the symbols of comment, if you need to remove it, you can do it by editing the three functions which I had written below.Test case which i had tested.
// helloworld
/* comment */
a /* comment */
b
/*
comment
*/
c
d
e
// xxxx
f // xxxx
The Output will be:
//
/* */
a /* */
b
/*
*/
c
d
e
//
f //
In this program I didn't remove the comment symbol as I was making lexical analyzer.You can remove the comment symbols by editing the program statements where i had put the comments.
public class testSpace {
public static void main(String[] args) {
try {
String filePath = "C:\\Users\\Sibil\\eclipse-workspace\\Assignment1\\src\\Input.txt";
FileReader fr = new FileReader(filePath);
String line;
BufferedReader br = new BufferedReader(fr);
int lineNumber = 0;
while ((line = br.readLine()) != null) {
lineNumber++;
if ((line.contains("/*") && line.contains("*/")) || (line.contains("//"))) {
line = findreplacement(line);
System.out.println(line);//Begining of the multiline comment
} else if (line.contains("/*")) {
line = getStartString(line);
System.out.println(line);
while ((line = br.readLine()) != null) {
lineNumber++;
if (line.contains("*/")) {
line = getEndString(line);
System.out.println(line);//Print the end of a Multline comment
break;
} else {
line = " ";
System.out.println(line);//Blank Space for commented line inside a multiline comment
}
}
} else
System.out.println(line);//Line without comment
}
} catch (Exception e) {
System.out.println(e);
}
}
private static String getEndString(String s) {
int end = s.indexOf("*/");
String lineEnd = s.substring(end, s.length());//Edit here if you don't need the comment symbol by substracting 2 or adding 2
return lineEnd;
}
private static String getStartString(String s) {
int start = s.indexOf("/*");
String lineStart = s.substring(0, start + 2);//Edit here if you don't need the comment symbol by substracting 2 or adding 2
return lineStart;
}
private static String findreplacement(String s) {
String line = "";
if (s.contains("//")) {
int start = s.indexOf("//");
line = s.substring(0, start + 2);//Edit here if you don't need the comment symbol by substracting 2 or adding 2
} else if ((s.contains("/*") && s.contains("*/"))) {
int start = s.indexOf("/*");
int end = s.indexOf("*/");
String lineStart = s.substring(0, start + 2);//Edit here if you don't need the comment symbol by substracting 2 or adding 2
String lineEnd = s.substring(end, s.length());//Edit here if you don't need the comment symbol by substracting 2 or adding 2
line = lineStart + " " + lineEnd;
}
return line;
}
}
If your file has a line like this,
System.out.println("Hello World/*Do Something */");
It will fail and the output will be:
System.out.println("Hello world");
I have a text file named "message.txt" which is read using Buffer Reader. Each line of the text file contains both "word" and "meaning" as given in this example:
"PS:Primary school"
where PS - word, Primary school - meaning
When the file is being read, each line is tokenized to "word" and "meaning" from ":".
If the "meaning" is equal to the given input string called "f_msg3", "f_msg3" is displayed on the text view called "txtView". Otherwise, it displays "f_msg" on the text view.
But the "if condition" is not working properly in this code. For example if "f_msg3" is equal to "Primary school", the output on the text view must be "Primary school". But it gives the output as "f_msg" but not "f_msg3". ("f_msg3" does not contain any unnecessary strings.)
Can someone explain where I have gone wrong?
try {
BufferedReader file = new BufferedReader(new InputStreamReader(getAssets().open("message.txt")));
String line = "";
while ((line = file.readLine()) != null) {
try {
/*separate the line into two strings at the ":" */
StringTokenizer tokens = new StringTokenizer(line, ":");
String word = tokens.nextToken();
String meaning = tokens.nextToken();
/*compare the given input with the meaning of the read line */
if(meaning.equalsIgnoreCase(f_msg3)) {
txtView.setText(f_msg3);
} else {
txtView.setText(f_msg);
}
} catch (Exception e) {
txtView.setText("Cannot break");
}
}
} catch (IOException e) {
txtView.setText("File not found");
}
Try this
............
meaning = meaning.replaceAll("\\s+", " ");
/*compare the given input with the meaning of the read line */
if(meaning.equalsIgnoreCase(f_msg3)) {
txtView.setText(f_msg3);
} else {
txtView.setText(f_msg);
}
............
Otherwise comment the else part, then it will work.
I don't see any obvious error in your code, maybe it is just a matter
of cleaning the string (i.e. removing heading and trailing spaces, newlines and so on) before comparing it.
Try trimming meaning, e.g. like this :
...
String meaning = tokens.nextToken();
if(meaning != null) {
meaning = meaning.trim();
}
if(f_msg3.equalsIgnoreCase(meaning)) {
txtView.setText(f_msg3);
} else {
txtView.setText(f_msg);
}
...
A StringTokenizer takes care of numbers (the cause for your error) and other "tokens" - so might be considered to invoke too much complexity.
String[] pair = line.split("\\s*\\:\\s*", 2);
if (pair.length == 2) {
String word = pair[0];
String meaning = pair[1];
...
}
This splits the line into at most 2 parts (second optional parameter) using a regular expression. \s* stands for any whitespace: tabs and spaces.
You could also load all in a Properties. In a properties file the format key=value is convention, but also key:value is allowed. However then some escaping might be needed.
ArrayList vals = new ArrayList();
String jmeno = "Adam";
vals.add("Honza");
vals.add("Petr");
vals.add("Jan");
if(!(vals.contains(jmeno))){
vals.add(jmeno);
}else{
System.out.println("Adam je už v seznamu");
}
for (String jmena : vals){
System.out.println(jmena);
}
try (BufferedReader br = new BufferedReader(new FileReader("dokument.txt")))
{
String aktualni = br.readLine();
int pocetPruchodu = 0;
while (aktualni != null)
{
String[] znak = aktualni.split(";");
System.out.println(znak[pocetPruchodu] + " " +znak[pocetPruchodu + 1]);
aktualni = br.readLine();
}
br.close();
}
catch (IOException e)
{
System.out.println("Nezdařilo se");
}
try (BufferedWriter bw = new BufferedWriter(new FileWriter("dokument2.txt")))
{
int pocetpr = 0;
while (pocetpr < vals.size())
{
bw.write(vals.get(pocetpr));
bw.append(" ");
pocetpr++;
}
bw.close();
}
catch (IOException e)
{
System.out.println("Nezdařilo se");
}
I have a file with the following format.
.I 1
.T
experimental investigation of the aerodynamics of a
wing in a slipstream . 1989
.A
brenckman,m.
.B
experimental investigation of the aerodynamics of a
wing in a slipstream .
.I 2
.T
simple shear flow past a flat plate in an incompressible fluid of small
viscosity .
.A
ting-yili
.B
some texts...
some more text....
.I 3
...
".I 1" indicate the beginning of chunk of text corresponding to doc ID1 and ".I 2" indicates the beginning of chunk of text corresponding to doc ID2.
what I need is read the text between ".I 1" and ".I 2" and save it as a separate file like "DOC_ID_1.txt" and then read the text between ".I 2" and ".I 3"
and save it as a separate file like "DOC_ID_2.txt" and so on. lets assume that the number of .I # is not known.
I have tried this but cannot finish it. any help will be appreciated
String inputDocFile="C:\\Dropbox\\Data\\cran.all.1400";
try {
File inputFile = new File(inputDocFile);
FileReader fileReader = new FileReader(inputFile);
BufferedReader bufferedReader = new BufferedReader(fileReader);
String line=null;
String outputDocFileSeperatedByID="DOC_ID_";
//Pattern docHeaderPattern = Pattern.compile(".I ", Pattern.MULTILINE | Pattern.COMMENTS);
ArrayList<ArrayList<String>> result = new ArrayList<> ();
int docID =0;
try {
StringBuilder sb = new StringBuilder();
line = bufferedReader.readLine();
while (line != null) {
if (line.startsWith(".I"))
{
result.add(new ArrayList<String>());
result.get(docID).add(".I");
line = bufferedReader.readLine();
while(line != null && !line.startsWith(".I")){
line = bufferedReader.readLine();
}
++docID;
}
else line = bufferedReader.readLine();
}
} finally {
bufferedReader.close();
}
} catch (IOException ex) {
Logger.getLogger(ReadFile.class.getName()).log(Level.SEVERE, null, ex);
}
You want to find the lines which match "I n".
The regex you need is : ^.I \d$
^ indicates the beginning of the line. Hence, if there are some whitespaces or text before I, the line will not match the regex.
\d indicates any digit. For the sake of simplicty, I allow only one digit in this regex.
$ indicates the end of the line. Hence, if there are some characters after the digit, the line will not match the expression.
Now, you need to read the file line by line and keep a reference to the file in which you write the current line.
Reading a file line by line is much easier in Java 8 with Files.lines();
private String currentFile = "root.txt";
public static final String REGEX = "^.I \\d$";
public void foo() throws Exception{
Path path = Paths.get("path/to/your/input/file.txt");
Files.lines(path).forEach(line -> {
if(line.matches(REGEX)) {
//Extract the digit and update currentFile
currentFile = "File DOC_ID_"+line.substring(3, line.length())+".txt";
System.out.println("Current file is now : currentFile);
} else {
System.out.println("Writing this line to "+currentFile + " :" + line);
//Files.write(...);
}
});
Note : In order to extract the digit, I use a raw "".substring() which I consider as evil but it is easier to understand. You can do it in a better way with a Pattern and a Matcher :
With this regex : ".I (\\d)". (The same as before but with parenthesis which indicates what you will want to capture). Then :
Pattern pattern = Pattern.compile(".I (\\d)");
Matcher matcher = pattern.matcher(".I 3");
if(matcher.find()) {
System.out.println(matcher.group(1));//display "3"
}
Look up regex, Java has inbuilt libraries for this.
https://docs.oracle.com/javase/tutorial/essential/regex/
http://docs.oracle.com/javase/7/docs/api/java/util/regex/Pattern.html
These links will give you a starting point, effectively you can use counter to perform a pattern match against the string and store anything between the first pattern match and the second pattern match. This information can be output to a separate file using the Formatter class.
Found here:-
http://docs.oracle.com/javase/7/docs/api/java/util/Formatter.html
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.PrintWriter;
public class Test {
/**
* #param args
* #throws IOException
*/
public static void main(String[] args) throws IOException {
// TODO Auto-generated method stub
String inputFile="C:\\logs\\test.txt";
BufferedReader br = new BufferedReader(new FileReader(new File(inputFile)));
String line=null;
StringBuilder sb = new StringBuilder();
int count=1;
try {
while((line = br.readLine()) != null){
if(line.startsWith(".I")){
if(sb.length()!=0){
File file = new File("C:\\logs\\DOC_ID_"+count+".txt");
PrintWriter writer = new PrintWriter(file, "UTF-8");
writer.println(sb.toString());
writer.close();
sb.delete(0, sb.length());
count++;
}
continue;
}
sb.append(line);
}
} catch (Exception ex) {
ex.printStackTrace();
}
finally {
br.close();
}
}
}