I'm trying to migrate and parse a database to a new schema using Java.
Problem is there are some characters, specially arab, which get messed up while treating the data in Java.
Here's one of the lines where I'm getting trouble with which is in countryToParse.sql file:
(4, 'Afganistán', 1, 'Afgano', 'Afghanistan', 'AF', 'أفغانستان', 'Afghan', 'أفغاني');
After I parse it, the resulting line in countryParsed.sql is seen as:
(4, 'Afganistán', 1, 'Afgano', 'Afghanistan', 'AF', 'أ�?غانستان', 'Afghan', 'أ�?غاني');
You see how there are certain arabic characters that get messed up.
If I open the files I can check they are both coded in UTF-8.
Here's the Java code I'm using. In method writeToTextFile() I've added three ways I found to write a file using UTF-8 (not to mention I'm getting the same error using them three ways)
public class MainStackOverflow {
public static void main(String[] args) throws IOException {
String countryStr = new String(readTextFile("src/data/countryToParse.sql").getBytes(), "UTF-8");
writeToTextFile("src/data/countryParsed.sql", countryStr);
}
public static String readTextFile(String fileName) throws IOException {
String content = new String(Files.readAllBytes(Paths.get(fileName)));
return content;
}
public static void writeToTextFile(String fileName, String content) throws IOException {
/* Way 1 */
Files.write(Paths.get(fileName), content.getBytes("UTF-8"), StandardOpenOption.CREATE);
/* Way 2 */
BufferedWriter out = new BufferedWriter(new OutputStreamWriter(
new FileOutputStream(fileName), "UTF-8"));
try {
out.write(content);
} finally {
out.close();
}
/* Way 3 */
PrintWriter out1 = new PrintWriter(new File(fileName), "UTF-8");
out1.write(content);
out1.flush();
out1.close();
/* */
}
}
You forgot to set the encoding in this line:
String content = new String(Files.readAllBytes(Paths.get(fileName)));
Try simply this:
public static void main(String[] args) throws IOException {
String countryStr = new String(readTextFile("src/data/countryToParse.sql"), "UTF-8");
writeToTextFile("src/data/countryParsed.sql", countryStr);
}
public static byte[] readTextFile(String fileName) throws IOException {
return Files.readAllBytes(Paths.get(fileName));
}
Related
I m trying to wrap FileinputStream and change close method of Parent in my wrapper class "Amigo". As u can see in code, i use default FileInputStream object to write some data in end of file in case of using .close() method. But, despite that i use "append" to "true" flag in the fileOutputStream field, my programm is still overwrites data in file. Why is this happens?
public class AmigoOutputStream extends FileOutputStream{
public static String fileName = "C:\\Users\\Егор\\IdeaProjects\\JavaRushTasks\\2.JavaCore\\src\\com\\javarush\\task\\task18\\task1813\\r.txt";
private FileOutputStream fileOutputStream = new FileOutputStream(fileName,true);
private static final String JAVA_RUSH = "JavaRush © All rights reserved.";
public AmigoOutputStream(FileOutputStream name) throws FileNotFoundException {
super(String.valueOf(name),true);
}
public static void main(String[] args) throws IOException {
new AmigoOutputStream(new FileOutputStream(fileName)).close();
}
#Override
public void close() throws IOException {
fileOutputStream.flush();
fileOutputStream.write(JAVA_RUSH.getBytes());
fileOutputStream.close();
}
}
The line with new FileOutputStream(fileName) inside main will wipe the file and that runs before new FileOutputStream(fileName,true) which is inside the class.
You are also creating a new file which has an unusual name - set to String.valueOf(name). You may want something like this which allows caller to specify the file and means AmigoOutputStream always sends extra bytes to some file:
public class AmigoOutputStream extends FileOutputStream{
private static final String JAVA_RUSH = "JavaRush © All rights reserved.";
public AmigoOutputStream(String name) throws FileNotFoundException {
super(name,true);
}
public static void main(String[] args) throws IOException {
try(OutputStream os = new AmigoOutputStream("r.txt")) {
}
}
#Override
public void close() throws IOException {
write(JAVA_RUSH.getBytes());
super.close();
}
}
I am having a bit of an issues trying to pass in a file read by my program and sorted accordantly. I am not used to working with files, and i ran out of ideas as to how this could be achieved.
/////////////////////////////////////// class reads file ///////////////////////////////////
import java.io.*;
public class InFileReader {
private BufferedReader inputStream = null;
private String fileLine;
private StringBuilder sb;
public String getFile(File fileRead) throws FileNotFoundException,
IOException {
inputStream = new BufferedReader(new FileReader(fileRead)); //reads files
sb = new StringBuilder();
while((fileLine = inputStream.readLine()) != null){//keep reading lines in file till there is none
sb.append(fileLine).append("\n");
}
return sb.toString(); //returns StringBuffer read values in String form
}
}
///////////////////////////////////////////////////// end of read file class ///////////////////////
public void getFile(File fileRead) throws FileNotFoundException,
IOException {
try {
String input = fileReader.getFile(fileRead.getAbsoluteFile());
HashMap<Integer, Thing.Ship> hashmap = new HashMap<>();
while (!input.isEmpty()) { // as long as there is data in the file keep looping
Scanner sc = new Scanner(input); // scan file
if (!input.startsWith("//")) { // take out "//" from directory
String type = "";
if (sc.hasNext()) { // if there are character lines get next line
type = sc.next();
}
if (type.equalsIgnoreCase("port")) { // looks for "port"
world.assignPort(new Thing.SeaPort(sc)); // assigns value to Seaport
} else if (type.equalsIgnoreCase("dock")) {
world.assignDock(new Thing.Dock(sc));
} else if (type.equalsIgnoreCase("ship")) {
Thing.Ship s = new Thing.Ship(sc);
hashmap.put(s.getIndex(), s);
world.assignShip(s);
} else if (type.equalsIgnoreCase("pship")) {
Thing.Ship s = new Thing.PassengerShip(sc);
hashmap.put(s.getIndex(), s);
world.assignShip(s);
} else if (type.equalsIgnoreCase("cship")) {
Thing.Ship s = new Thing.CargoShip(sc);
hashmap.put(s.getIndex(), s);
world.assignShip(s);
} else if (type.equalsIgnoreCase("person")) {
world.assignPerson(new Thing.Person(sc));
}
}
}
//inputOut.setText(type);
inputOut.setText(world.toString());
} catch (Exception e) {
System.out.println(e + "-----");
}
}
Here fileRead knows where to find the file to be read "C:\Users\abe\IdeaProjects\CreateSeaPortDataFile\src\text.txt"
public void getFile(File fileRead) throws FileNotFoundException,
IOException {
this is where things just fall apart:
String input = fileReader.getFile(fileRead.getAbsoluteFile());
My intent here is to pass the location of the file so that the getFile class can read it and then be sorted into the hashmap.
again i am not familiar with how to work with file, any suggestion or comment would be greatly appreciated.
thank you in advanced.
If you get a FileNotFoundException then the file was not found.
You say the filename was "C:\Users\abe\IdeaProjects\CreateSeaPortDataFile\src\text.txt".
If you type that name in the code you must escape the backslash:
"C:\\Users\\abe\\IdeaProjects\\CreateSeaPortDataFile\\src\\text.txt".
I wanted to create log.html file using java wherein i'll dump errors into html table-row as and when errors are caught.
I created table columns but when i am passing anything to it then my data is overwriting column names instead of appending row.
My java code is as follows:
public static void main(String[] args) throws IOException
{
String month = getMonth(1);
System.out.println(month);
//table(month);
addrow("abc");
}
public static void table(String Update) throws IOException
{
//define a HTML String Builder
StringBuilder htmlStringBuilder=new StringBuilder();
htmlStringBuilder.append("<html><head><title>Packaging Issues</title></head>");
htmlStringBuilder.append("<body><h1> Files Received </h1>");
htmlStringBuilder.append("<table border=\"1\" bordercolor=\"#000000\">");
htmlStringBuilder.append("<tr><td><b>Cycle</b></td><td>"+Update+"</td></tr>");
htmlStringBuilder.append("<tr><td><b>Version</b></td><td></tr>");
newtable(htmlStringBuilder.toString());
}
public static void newtable(String a)
{
StringBuilder htmlStringBuilder=new StringBuilder();
htmlStringBuilder.append(a);
htmlStringBuilder.append("<h1> Issues Found </h1>");
htmlStringBuilder.append("<table border=\"1\" bordercolor=\"#000000\">");
htmlStringBuilder.append("<tr><td><b>Type</b></td>");
htmlStringBuilder.append("<td><b>Field</b></td>");
htmlStringBuilder.append("<td><b>Issue</b></td></tr>");
addrow(htmlStringBuilder.toString());
// WriteToFile(htmlStringBuilder.toString(),"log.html");
}
public static void addrow(String a)
{
try {
StringBuilder htmlStringBuilder=new StringBuilder();
htmlStringBuilder.append("<tr><td><b>"+a+"</b></td>");
htmlStringBuilder.append("<td><b>Field</b></td>");
htmlStringBuilder.append("<td><b>Issue</b></td></tr>");
htmlStringBuilder.append("</table></body></html>");
WriteToFile(htmlStringBuilder.toString(),"log.html");
} catch (IOException e) {
e.printStackTrace();
}
}
Here's the writetofile method:
public static void WriteToFile(String fileContent, String fileName) throws IOException {
String projectPath = "/home/abc";
String tempFile = projectPath + File.separator+fileName;
File file = new File(tempFile);
// if file does exists, then delete and create a new file
//write to file with OutputStreamWriter
OutputStream outputStream = new FileOutputStream(file.getAbsoluteFile());
Writer writer=new OutputStreamWriter(outputStream);
writer.write(fileContent);
writer.close();
}
The constructor FileOutputStream(file) overwrites the contents of the file. Use this constructor instead
FileOutputStream fos =new FileOutputStream(file, true) ;
I want to add lots of data to a file. I defined the HYB class since my object contains ofdifferent types of data (String and byte[]). I used ObjectOutputStream and ObjectInputStream to write and read from the file. But my code does not print the expected result. To write my code I used code in the following pages:
How can I append to an existing java.io.ObjectStream?
ClassCastException when Appending Object OutputStream
I try to debug my code and found the problem but I could not. This is my code:
import java.io.*;
import java.io.BufferedOutputStream;
import java.util.*;
public class HYB implements Serializable
{
private static final long serialVersionUID = 1L;
private List<byte[]> data = new ArrayList<>();
public void addRow(String s,byte[] a)
{
data.add(s.getBytes()); // add encoding if necessary
data.add(a);
}
#Override public String toString()
{
StringBuilder sb = new StringBuilder();
synchronized (data)
{
for(int i=0;i<data.size();i+=2)
{
sb.append(new String(data.get(i)));
sb.append(Arrays.toString(data.get(i+1))+"\n");
}
}
return sb.toString();
}
private static void write(File storageFile, HYB hf)
throws IOException {
ObjectOutputStream oos = getOOS(storageFile);
oos.writeObject(hf);
oos.flush();
oos.close();
}
public static ObjectOutputStream getOOS(File file) throws IOException
{
if (file.exists()) {
return new AppendableObjectOutputStream(new FileOutputStream(file, true));
} else {
return new ObjectOutputStream(new FileOutputStream(file));
}
}
private static ObjectInputStream getOIS(FileInputStream fis)
throws IOException {
long pos = fis.getChannel().position();
return pos == 0 ? new ObjectInputStream(fis) :
new AppendableObjectInputStream(fis);
}
private static class AppendableObjectOutputStream extends
ObjectOutputStream {
public AppendableObjectOutputStream(OutputStream out)
throws IOException {
super(out);
}
#Override
protected void writeStreamHeader() throws IOException {
}
}
private static class AppendableObjectInputStream extends ObjectInputStream {
public AppendableObjectInputStream(InputStream in) throws IOException {
super(in);
}
#Override
protected void readStreamHeader() throws IOException {
// do not read a header
}
}
public static void main(String[] args) throws FileNotFoundException, IOException, ClassNotFoundException
{
File x=new File ("test");
HYB hf1 = new HYB();
hf1.addRow("fatemeh",new byte[] {11,12,13});
hf1.addRow("andisheh",new byte[] {14,15,16});
write(x,hf1);
HYB hf = new HYB();
hf.addRow("peter",new byte[] {1,2,3});
hf.addRow("jaqueline",new byte[] {4,5,6});
write(x,hf);
FileInputStream fis = new FileInputStream(x);
HYB hf2 = (HYB) getOIS(fis).readObject();
System.out.println(hf2);
}
}
expected results:
fatemeh[11, 12, 13]
andisheh[14, 15, 16]
peter[1, 2, 3]
jaqueline[4, 5, 6]
actual results:
fatemeh[11, 12, 13]
andisheh[14, 15, 16]
Writing the two HYB objects to the ObjectOutputStream doesn't merge them into a single HYB object; the ObjectOutputStream still contains two HYB object, of which your code reads one. If you did a second call to readObject(), the second one would be retrieved and could be printed to the screen. So you could just wrap the readObject() and println() calls in a loop that reads/writes until there's nothing else to read from the stream.
You are writing two HYB objects to the stream, but only reading one out.
You need to readObject() twice.
I am generating dynamic page using JSP, I want to save this dynamically generated complete page in file as archive.
In JSP, everything is written to PrintWriter out = response.getWriter();
At the end of page, before sending response to client I want to save this page, either in file or in buffer as string for later treatment.
How can I save Printwriter content or convert to String?
To get a string from the output of a PrintWriter, you can pass a StringWriter to a PrintWriter via the constructor:
#Test
public void writerTest(){
StringWriter out = new StringWriter();
PrintWriter writer = new PrintWriter(out);
// use writer, e.g.:
writer.print("ABC");
writer.print("DEF");
writer.flush(); // flush is really optional here, as Writer calls the empty StringWriter.flush
String result = out.toString();
assertEquals("ABCDEF", result);
}
Why not use StringWriter instead? I think this should be able to provide what you need.
So for example:
StringWriter strOut = new StringWriter();
...
String output = strOut.toString();
System.out.println(output);
It will depend on: how the PrintWriter is constructed and then used.
If the PrintWriter is constructed 1st and then passed to code that writes to it, you could use the Decorator pattern that allows you to create a sub-class of Writer, that takes the PrintWriter as a delegate, and forwards calls to the delegate, but also maintains a copy of the content that you can then archive.
public class DecoratedWriter extends Writer
{
private final Writer delegate;
private final StringWriter archive = new StringWriter();
//pass in the original PrintWriter here
public DecoratedWriter( Writer delegate )
{
this.delegate = delegate;
}
public String getForArchive()
{
return this.archive.toString();
}
public void write( char[] cbuf, int off, int len ) throws IOException
{
this.delegate.write( cbuf, off, len );
this.archive.write( cbuf, off, len );
}
public void flush() throws IOException
{
this.delegate.flush();
this.archive.flush();
}
public void close() throws IOException
{
this.delegate.close();
this.archive.close();
}
}
You cannot get it with just your PrintWriter object. It flushes the data, and does not hold any content within itself. This isn't the object you should be looking at to get the entire string,
The best way I think is prepare your response in other object like StringBuffer, and fush its content to the response, and after save the content stored in that variable to the file.
This helped me: for obtaining a SOAP-able object as XML string.
JAXBContext jc = JAXBContext.newInstance(o.getClass());
Marshaller m = jc.createMarshaller();
StringWriter writer = new StringWriter();
m.marshal( o, new PrintWriter(writer) );
return writer.toString();
Along similar lines to what cdc is doing - you can extend PrintWriter and then create and pass around an instance of this new class.
Call getArchive() to get a copy of the data that's passed through the writer.
public class ArchiveWriter extends PrintWriter {
private StringBuilder data = new StringBuilder();
public ArchiveWriter(Writer out) {
super(out);
}
public ArchiveWriter(Writer out, boolean autoFlush) {
super(out, autoFlush);
}
public ArchiveWriter(OutputStream out) {
super(out);
}
public ArchiveWriter(OutputStream out, boolean autoFlush) {
super(out, autoFlush);
}
public ArchiveWriter(String fileName) throws FileNotFoundException {
super(fileName);
}
public ArchiveWriter(String fileName, String csn) throws FileNotFoundException, UnsupportedEncodingException {
super(fileName, csn);
}
public ArchiveWriter(File file) throws FileNotFoundException {
super(file);
}
public ArchiveWriter(File file, String csn) throws FileNotFoundException, UnsupportedEncodingException {
super(file, csn);
}
#Override
public void write(char[] cbuf, int off, int len) {
super.write(cbuf, off,len);
data.append(cbuf, off, len);
}
#Override
public void write(String s, int off, int len) {
super.write(s, off,len);
data.append(s, off, len);
}
public String getArchive() {
return data.toString();
}
}