I am quite new in java, I need to save xml to csv using java, but problem is I cannot use CSVWriter because in xml there are also UTF8 encoded data.
Therefore I found out it is possible to use outputstreamwriter, which can be encoded in UTF8.
For string everything is ok, but for integer I cannot get correct number.
Sample code:
import java.io.BufferedWriter;
import java.io.FileOutputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.util.*;
public class UTF8WriterDemo {
public static void main(String[] args) {
Writer out = null;
try {
out = new BufferedWriter(
new OutputStreamWriter(new FileOutputStream("c://java2//file.csv"), "windows-1250"));
//for (int i=0; i<4; i++ ) {
String text = "This tečt will be added to File !!";
int hu = 4;
out.write('\ufeff');
out.write(text+ '\n');
out.write(hu+ '\n');
//}
out.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
I get picture instead of a number.
I suppose it's because:
An OutputStreamWriter is a bridge from character streams to byte streams: Characters written to it are encoded into bytes using a specified charset. The charset that it uses may be specified by name or may be given explicitly, or the platform's default charset may be accepted.
And that's why it's not displayed correctly.
Therefore I would like to ask, is there any option for integers to be displayed using outputstreamwriter?
Or if not, how can I convert xml data into csv using java for UTF8 encoded characters?
Thank you
Java has a difference between using double quotes and single quotes.
"foo" is a String.
'f' is a char (or Character)
'foo' will throw an Exception, because you can only have 1 character in a char.
'\n' is also 1 character, specifically the newline character. Adding a number and a character will use the number as an ASCII value and use the corresponding character, then combine both characters into a String (or array of characters, ie. char[]).
Using double quotes should fix your issue.
import java.io.*;
public class UTF8WriterDemo {
public static void main(String[] args) {
Writer out = null;
try {
out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("file.csv"), "windows-1250"));
//for (int i = 0; i < 4; i++) {
String text = "This text will be added to File !!";
int hu = 4;
String text2 = new String("" + hu);
out.write('\ufeff');
out.write(text + '\n');
out.write(text2 + '\n');
// }
out.close();
} catch (Exception e) {
e.printStackTrace();
} finally {
System.out.println("The process is completed.");
}
}
}
actually I need to rewrite this construction:
FileWriter fileWriter = new
FileWriter("C:\\java\\test\\EEexample3.csv");
CSVWriter csvWriter = new CSVWriter(fileWriter);
csvWriter.writeNext(new String[] {
..
..
..
..
}
..code.. code..
String homeCurrencyPriceString = iit.getHomeCurrency().getPrice()!=null?iit.getHomeCurrency().getPrice().toString():"";
String headerDateString = invoiceHeaderType.getDateTax()!=null?invoiceHeaderType.getDateTax().toString():"";
String invoiceTypeString = invoiceHeaderType.getInvoiceType()!=null?invoiceHeaderType.getInvoiceType().value():"";
String headeraccountno= invoiceHeaderType.getAccount().getAccountNo()!=null?invoiceHeaderType.getAccount().getAccountNo().toString():"";
String headertext = invoiceHeaderType.getText()!=null?invoiceHeaderType.getText():"";
String invoiceitemtext= iit.getText()!=null?iit.getText():"";
String headericdph = invoiceHeaderType.getPartnerIdentity().getAddress().getIcDph()!=null?invoiceHeaderType.getPartnerIdentity().getAddress().getIcDph():"";
String symVar = invoiceHeaderType.getSymVar()!=null?invoiceHeaderType.getSymVar():"";
csvWriter.writeNext(new String[] {
invoiceHeaderType.getPartnerIdentity().getAddress().getIco(), headericdph, invoiceHeaderType.getPartnerIdentity().getAddress().getCompany(),symVar, invoiceHeaderType.getId().toString(), iit.getId().toString(), homeCurrencyPriceString, detailcentreString,headercentreString, headerDateString, invoiceTypeString,headeraccountno, headertext,invoiceitemtext
});
where objects are filled by xml
to outputstreamwriter construction.
So first I am trying outputstream as simple code, to be sure it`s working , next when it works, I wanted to rewrite the whole code.
Using CSVwriter everything works smoothly, just now there were added texts encoded in UTF8/windows1250 :( Therefore I need to fix the construction of code.
Even number objects like price are converted using .toString(), so maybe it works without int.
I hope writer of outputstreamwriter is able to do what is necessary.
I am going to try.
Related
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);
}
}
}
}
So I'm supposed to insert information in a file with UTF-16 encoding, than do some operations (count lines, words, etc). Problem is that if I choose the UTF-16 encoding, an exception is thrown, but the UTF-8 works fine.
import java.io.*;
import java.util.Scanner;
public final class Q4 {
public static void main(String[ ] args)throws FileNotFoundException{
final String ENCODING = "UTF-16";
final String FILE = " testcount";
PrintWriter out = null;
// Given code – do not modify(!) This will create the UTF-16 test file on your drive.
try {
out = new PrintWriter(FILE, ENCODING);
out.write("Test file for UTF-16\n" + "(contains surrogate pairs:\n" +
"Musical symbols in the range 1D100–1D1FF)\n\n");
out.write("F-clef (1D122): \uD834\uDD22\tCrotchet (1D15F): \uD834\uDD5F\n");
out.write("G-clef (1D120): \uD834\uDD20\tSemiquaver (1D161): \uD834\uDD61\n");
out.write("\n(? lines, ?? words, ??? chars but ??? code points)\n");
} catch (IOException e) { System.out.println("uh? cannot write to file!");
} finally { if (out != null) out.close();
}
// Your code – scan the test file and count lines, words, characters, and code points.
Scanner fin = new Scanner(new File(FILE));
String s = "";
//get the data in file
while (fin.hasNext()){
s = s + fin.next();
System.out.println(s);
}
fin.close();
//count words and lines
}
}
My only guess, a far fetched one, is that it has to something to do with the OS (windows 8.1) not being able to save a UTF- 16 code, but sounds like a silly guess.
Specify the encoding when you read the file:
Scanner fin = new Scanner(new File(FILE), ENCODING);
I want to split string by new lines in Java.I am using following regex -
str.split("\\r|\\n|\\r\\n");
But still it is not splitting string by new lines.
Input -
0
0
0
0
Output = String [] array = {"0000"} instead I want = String [] array = {"0","0","0","0"}.
I have read various solutions on stack overflow but nothing works for me.
Code is -
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.text.DecimalFormat;
public class Input {
public static void main(String[] args) {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String line;
String text = "";
try {
while((line=br.readLine())!=null){
text = text + line;
}
} catch (IOException e) {
e.printStackTrace();
}
String [] textarray = text.trim().split("[\\r\\n]+");
for(int j=0;j<textarray.length;j++)
System.out.println(textarray[j]);
// System.out.print("");
// for(int i=((textarray.length)-1);i>=0;i--){
// long k = Long.valueOf(textarray[i]).longValue();
// System.out.println(k);
//// double sqrt = Math.sqrt(k);
//// double value = Double.parseDouble(new DecimalFormat("##.####").format(sqrt));
//// System.out.println(value);
////
//// }
}
When you call br.readLine(), the newline characters are stripped from the end of the string. So if you type 0 + ENTER four times, you are trying to split the string "0000".
You would be better to read items in from stdin and store them in an expandable data structure, such as a List<String>. No need to split things if you've already read them separately.
Updated Answer:
If you are reading the inputstreamfrom the keyboard, the \n may not be put into the data correctly. In that case, you may want to choose a new sentinel value.
Original Answer:
I believe you need to create a sentinel value. So if \n is your sentinel value, you could do something like this:
Load the inputstream into a string variable
Go character by character through the string variable checking to see if \n is in the input (you could use a for loop and the substing(i, i+2)
If it is found, then you could add it to an array
public void loadFromFile(String filename) {
File file = new File(filename);
BufferedReader br;
try {
br = new BufferedReader(new FileReader(file));
numberOfAttributes = Integer.parseInt(br.readLine());
}
...
}
Above is my program: I am trying to read from a txt file where the first line is the number 22 and nothing more. I don't know why the program gives me an exception.
Try stripping any whitespace from the string:
numberOfAttributes = Integer.parseInt(br.readLine().trim());
I think you might have a UTF-8 BOM (byte-order mark) at the start of your file.
Here's a class that reproduces the error:
import java.io.*;
public class BomTest {
public static void main(String[] args) throws Exception {
File file = new File("example.txt");
// Write out UTF-8 BOM, followed by the number 22 and a newline.
byte[] bs = { (byte)0xef, (byte)0xbb, (byte)0xbf, (byte)'2', (byte)'2', 10 };
FileOutputStream fos = new FileOutputStream(file);
fos.write(bs);
fos.close();
BufferedReader r = new BufferedReader(new FileReader(file));
String s = r.readLine();
System.out.println(Integer.parseInt(s));
}
}
When I run this class, I get the following output:
luke#computer:~$ java BomTest
Exception in thread "main" java.lang.NumberFormatException: For input string: "22"
at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
at java.lang.Integer.parseInt(Integer.java:481)
at java.lang.Integer.parseInt(Integer.java:514)
at BomTest.main(BomTest.java:15)
There isn't really an easy way to deal with UTF-8 BOMs in Java; it's best not to generate them in the first place. See also this answer.
br.readLine() reads the entire line including the new line special character.Apart, form the solution suggested by James, you can use Scanner#nextInt().
try with numberOfAttributes = Integer.parseInt(br.readLine().trim());
public String trim()
Returns a copy of the string, with leading and trailing whitespace
omitted. If this String object represents an empty character sequence,
or the first and last characters of character sequence represented by
this String object both have codes greater than '\u0020' (the space
character), then a reference to this String object is returned.
Otherwise, if there is no character with a code greater than '\u0020'
in the string, then a new String object representing an empty string
is created and returned.
This happens because you have a space in the input line. Look at these:
int i1 = Integer.parseInt("22 ");
int i2 = Integer.parseInt("22a");
int i3 = Integer.parseInt("2 2");
int i4 = Integer.parseInt("22\n");
All of them generate exception. I suggest you to trim, tokenize or substitute. But in general, it doesn't sound to me a good solution to read a number from a file in that way.
If you really need to store data, why don't you create an object ad hoc and serialize/deserialize it?
You might have a null character in your string. Remove it using a regEx "\d+".
NumberFormatException is raised because the input string is not in expected number format. Generally, you can see 'the wrong string input' in the error message and can easily identify the bug. But in your case, the catch is that the error message does not display the string input completely (because it does not displays the null character).
Check the below output and the code.
public class TestParseInt{
private static final Pattern pattern = Pattern.compile("\\d+");
public static void main(String []args){
String a = "22\0";
try {
System.out.println("Successfull parse a: " + Integer.parseInt(a));
} catch(NumberFormatException e) {
System.out.println("Error:" +e.getMessage());
}
try {
Matcher matcher = pattern.matcher(a);
if(matcher.find()) {
System.out.println("Succesfull parse a: " +
Integer.parseInt(matcher.group(0)));
}
} catch(NumberFormatException e) {
System.out.println("Error" + e.getMessage());
}
}
}
Output:
Error:For input string: "22"
Succesfull parse a: 22
My Sample Code
String line = null;
RandomAccessFile file = new RandomAccessFile("D:/mahtew.txt", "rw");
System.out.println(file.getFilePointer());
while((line = file.readLine()) != null){
System.out.println(line);
System.out.println(file.getFilePointer());
if(line.contains("Text to be appended with")){
file.seek(file.getFilePointer());
file.write(" new text has been appended".getBytes());
break;
}
}
file.close();
demo.txt before execution
one two three
Text to be appended with
five six seven
eight nine ten
demo.txt after execution
one two three
Text to be appended with
new text has been appendedten
Also i tried using setLength to change length of file before new text is appended. But still some text is getting trimmed from output file. Any help will be appreciated
Thanks
Mathew
RandomAccessFile
A random access file behaves like a large array of bytes stored in the
file system.
In fact it does not care about shifting the array elements in the case of write operations (only the pointer is advanced). Such an operation overwrites existing values:
Output operations write bytes starting at the file pointer and advance
the file pointer past the bytes written.
When you seek to the file's byte location and writes data, the bytes will be overwritten.
Which is why you get an output like this.
Just imagine editing something in notepad with the insert key pressed. It will replace instead of inserting the new data in between. Same thing's happening here.
EDIT:
You should actually do what Eel is suggesting if you want to edit the file content.
Or you can get the rest of the file and add it to the modified data and write to the file in order to avoid the loss, but that will get ugly and complicated real fast. Not to mention performance penalties.
Understand that when you write with a RAF, you over-write data which was previously held at the file pointer location. If you want to insert text into a file, I suggest that you not use a RAF but rather simply read the text of the file into a String or ArrayList<String> or StringBuilder, using a File held by a FileReader wrapped in a BufferedReader or a File wrapped in a Scanner, alter the Strings or StringBuilder held in memory, and then write the altered data to the new file using a FileWriter wrapped in a PrintWriter.
e.g.,
import java.io.File;
import java.io.FileNotFoundException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
public class AppendLine {
private static final String FILE_PATH = "src/tetris/mahtew.txt";
private static final String MARKER_LINE = "Text to be appended with";
private static final String TEXT_TO_ADD = "new text has been appended";
public static void main(String[] args) {
List<String> fileLines = new ArrayList<String>();
Scanner scanner = null;
try {
scanner = new Scanner(new File(FILE_PATH));
while (scanner.hasNextLine()) {
String line = scanner.nextLine();
fileLines.add(line);
if (line.trim().equalsIgnoreCase(MARKER_LINE)) {
fileLines.add(TEXT_TO_ADD);
}
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} finally {
if (scanner != null) {
scanner.close();
}
}
PrintWriter pw = null;
try {
pw = new PrintWriter(new File(FILE_PATH));
for (String line : fileLines) {
pw.println(line);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} finally {
if (pw != null) {
pw.close();
}
}
}
}
You can use RandomAccessFile in Java to achieve this on one condition:
The size of each line has to be fixed otherwise, when new string is written back, it might override the string in the next line.
Therefore, in my example, I set the line length as 100 and padding with space string when creating the file and writing back to the file.
So in order to allow update, you need to set the length of line a little larger than the longest length of the line in this file.
public class RandomAccessFileUtil {
public static final long RECORD_LENGTH = 100;
public static final String EMPTY_STRING = " ";
public static final String CRLF = "\n";
public static final String PATHNAME = "/home/mjiang/JM/mahtew.txt";
/**
* one two three
Text to be appended with
five six seven
eight nine ten
*
*
* #param args
* #throws IOException
*/
public static void main(String[] args) throws IOException
{
String starPrefix = "Text to be appended with";
String replacedString = "new text has been appended";
RandomAccessFile file = new RandomAccessFile(new File(PATHNAME), "rw");
String line = "";
while((line = file.readLine()) != null)
{
if(line.startsWith(starPrefix))
{
file.seek(file.getFilePointer() - RECORD_LENGTH - 1);
file.writeBytes(replacedString);
}
}
}
public static void createFile() throws IOException
{
RandomAccessFile file = new RandomAccessFile(new File(PATHNAME), "rw");
String line1 = "one two three";
String line2 = "Text to be appended with";
String line3 = "five six seven";
String line4 = "eight nine ten";
file.writeBytes(paddingRight(line1));
file.writeBytes(CRLF);
file.writeBytes(paddingRight(line2));
file.writeBytes(CRLF);
file.writeBytes(paddingRight(line3));
file.writeBytes(CRLF);
file.writeBytes(paddingRight(line4));
file.writeBytes(CRLF);
file.close();
System.out.println(String.format("File is created in [%s]", PATHNAME));
}
public static String paddingRight(String source)
{
StringBuilder result = new StringBuilder(100);
if(source != null)
{
result.append(source);
for (int i = 0; i < RECORD_LENGTH - source.length(); i++)
{
result.append(EMPTY_STRING);
}
}
return result.toString();
}
}
If replaced string is too long, the strings after the line matched with input will be replaced. It seems you have to read file, modify it and write back to old or new file.
Of course, you have options to use multi-threading programming and Java 7's new IO features to improve performance.