I have just started learning Java and I have got following problem I have been struggling for hours with. I want to use PrintWriter in order to produce a simple text file.
I do not get any runtime exception, still the file is not appearing in the specified directory.
public class Main {
public static void main(String[] args) {
try (final PrintWriter writer = new PrintWriter(
new File("c:\test\new\notes.txt"))) {
writer.write("Test note");
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
What am I doing wrong?
\ represents an escape character so needs to be escaped itself for literal backslash characters. You can also use / and Java will resolve the correct separation character for the platform
try (final PrintWriter writer = new PrintWriter("c:\\test\new\\notes.txt")) {
Add writer.flush() after writer.write("Test note"), and use double backslashes for Windows paths (as other answers are suggesting).
As Reimeus already said, \ is an escape character in java.
That means that a string containing "\n" or "\t" does not represent the stringliteral \n or \t!
'\n' represents the newline character and '\t' represents the TAB character!
For the better understanding, the following code:
System.out.println("c:\test\new\notes.txt");
would not print c:\test\new\notes.txt to the console, it would print
c: est
ew
otes.txt
to the console!
To be able to write the backslash in a string you'll need to use '\\'!
I see your question as having 2 parts:
Why doesn't the code work?
Why was no exception thrown?
The first question has already been answered, but I think the answer to the second question is at least as important because your current code will still fail silently if there is any problem writing to the file.
From the documentation of PrintWriter (http://docs.oracle.com/javase/7/docs/api/java/io/PrintWriter.html):
Methods in this class never throw I/O exceptions, although some of its
constructors may. The client may inquire as to whether any errors have
occurred by invoking checkError().
Therefore it is essential that you call checkerror() after every call to a PrintWriter method or your code will not be reliable.
Related
For example I've this file that should be formated like this:
PersonName
2,5,6,7,8,9
First line only has a name and from the second line onwards its all comma separated values.
Ending in a new line. For some reason I can't make a new empty line in code format.
Now lets say that those comma separated values will be copied into an ArrayList and then I check if the ArrayList is empty or not. If it is empty I've to throw an exception. My question is, what exception to throw here?
Something like (in pseudo code):
FileReader fr = new FileReader(f);
BufferedReader buffReader = new BufferedReader(fr);
ArrayList list = new ArrayList();
while(interator.hasCSV) {
// copy values to list
Object obj = interator.next();
list.add(obj);
}
if(list.isEmpty()) {
// What exception to throw here?
// It means there was a name in the file (first line) but then no csv values
}
I hope I made myself clear otherwise just let me know and I'll try to explain it better.
as paxdiablo said you can create your own exception here is an example link
class CheckListException extends Exception
{
//Parameterless Constructor
public CheckListException() {}
//Constructor that accepts a message
public CheckListException(List list)
{
super(list);
}
}
to use the exception
try
{
if(list.isEmpty()) {
// What exception to throw here?
// It means there was a name in the file (first line) but then no csv values
throw new CheckListException();
}
}
catch(CheckListException ex)
{
//Process message however you would like
}
Create your own exception. For further details follow this
if()//your condition
/*create custom exeception*/
throw new Exception("My custom exception");
}
But this is one time exception.
You have to follow the above link to create a new class for your custom exception to reuse.
There's no requirement to use the standard ones defined in Java since you can create whatever ones you need.
While it looks like (from here) the closest one in the standard set is probably DataFormatException (see here), that's targeted to ZIP files.
Perhaps a better match would be ParseException. If you wanted to use one of the more targeted standard ones, that would be the one I'd be looking to use (if you don't wish to create your own), or inherit from (if you do).
But keep in mind you can always inherit from the top-level Exception class if you're not overly concerned about where it is in the hierarchy.
It would be normal to place all the code responsible for parsing the content of the file in its own method. Most parsers interleave reading from the input stream and examining what it has read. Such a method must declare that it throws IOException, because the parts of the method that read from the input stream can throw an IOException. The parsing method will be easier to use if parse errors are also indicated by throwing an IOException: a caller of the method can use one catch to handle all problems, if they are not interested in the details of the problems.
A caller of the method might however want to be able to distinguish between different kinds of problems. The caller might want to report different error messages for a missing file and for an incorrectly formatted file. To support this, you could create your own InvalidFormatException that extends IOException and throw that when there is a parse error.
I don't have any idea about regex pattern matching, and I am having a problem with single quotes in file path when when I run batch file through exec() command, I get the following error i.e
Error is-
Windows cannot find 'C:\Program'.
I am having trouble with single quotes when CMD tries to get into the desired directory.
So, anyone could tell me what to do here??
I created a batch file to compile and run java programs I have a function called createrunbat(String,String), and following code:
private File createrunbat(String str,String par)
{
if(str.startsWith("Text Editor-",0))
{
str=str.replaceFirst("Text Editor-","");
}
String sng,s2;
File fe;
try{
FileOutputStream fos;
DataOutputStream dos;
sng=str;
int a=sng.indexOf(".");
sng=sng.substring(0,a);
file=new File(jfc.getSelectedFile().getParent(),sng+".bat");
fd=file.getAbsoluteFile();
str=fd.getParent().substring(0, 2);
fos=new FileOutputStream(file);
dos=new DataOutputStream(fos);
dos.writeBytes("#echo off \n");
dos.writeBytes("cd\\"+"\n");
if(fd.getParentFile().isDirectory())
{
dos.writeBytes(str+"\n");
}
s2=jfc.getSelectedFile().getParent();//I am having single quote problem from here
dos.writeBytes("cd "+s2+"\\"+"\n");
dos.writeBytes("javac "+sng+".java"+"\n");
dos.writeBytes("java "+sng+" "+par+"\n");
dos.writeBytes("pause \n");
dos.writeBytes("exit \n");
dos.close();
}
catch(FileNotFoundException ex)
{
}
catch(IOException ex2)
{
JOptionPane.showMessageDialog(this,ex2.toString());
}
return fd;
}
I think this is a rather more of a case that the blank in the path name is causing trouble and you will need to wrap quotes around the path
dos.writeBytes ("cd \"" + s2 +"\""+"\n");
You are perhaps confusing the error output with the input.
Windows cannot find 'C:\Program'.
The single quotes there are used to wrap the problematic data so you the developer know the boundaries of the input causing issues. The single quotes are not part of what your program interprets.
As others have suggested I imagine the real issue is the whitespace in your path. Your command line is reading the path as two separate arguments instead of one. Ironically, wrapping the path in quotes should fix the issue.
'C:\Program Files\SomePlace\...'
^ gets cut on whitespace and becomes two arguments instead of one:
'C:\Program' and 'Files\SomePlace\...'
'"C:\Program Files\SomePlace\..."'
^ quotes will keep the path together as a single argument
Edit: How to wrap the path.
Java1 has a good solution in their answer so I'll offer an alternative one that uses String formatting.
String safePath = String.format("\"%s\"", jfc.getSelectedFile().getParent().getAbsolutePath());
In this instance, the first argument to the String.format() method is the pattern to use, the second is the variable to substitute.
The actual quotes that will be around the path must be escaped (\") as they have a special meaning in java to denote the start or end of a String. You must escape them to use them inside a String. The place-holder is where your path will be placed (%s).
Side note:
You should really use much more descriptive variable names in your code. It is quite bad practice to use names like s2, sng, fe, fd and so on. Be descriptive and exact with your naming and following, debugging and writing your code will become easier.
I'm writing a simple program that writes data to the selected file .
everything is going great except the line breaks \n the string is written in the file but without line breaks
I've tried \n and \n\r but nothing changed
the program :
public void prepare(){
String content = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n\r<data>\n\r<user><username>root</username><password>root</password></user>\n\r</data>";
FileOutputStream fos = null;
try {
fos = new FileOutputStream(file);
} catch (FileNotFoundException ex) {
System.out.println("File Not Found .. prepare()");
}
byte b[] = content.getBytes();
try {
fos.write(b);
fos.close();
} catch (IOException ex) {
System.out.println("IOException .. prepare()");
}
}
public static void main(String args[]){
File f = new File("D:\\test.xml");
Database data = new Database(f);
data.prepare();
}
Line endings for Windows follow the form \r\n, not \n\r. However, you may want to use platform-dependent line endings. To determine the standard line endings for the current platform, you can use:
System.lineSeparator()
...if you are running Java 7 or later. On earlier versions, use:
System.getProperty("line.separator")
My guess is that you're using Windows. Write \r\n instead of \n\r - as \r\n is the linebreak on Windows.
I'm sure you'll find that the characters you're writing into the file are there - but you need to understand that different platforms use different default line breaks... and different clients will handle things differently. (Notepad on Windows only understands \r\n, other text editors may be smarter.)
The correct linebreak sequence on windows is \r\n not \n\r.
Also your viewer may interpret them differently. For example, notepad will only display CRLF linebreaks, but Write or Word have no problem displaying CR or LF alone.
You should use System.lineSeparator() if you want to find the linebreak sequence for the current platform. You are correct in writing them explicitly if you are attempting to force a linebreak format regardless of the current platform.
I have a minor problem, the \n's in my file isn't working in my output I tried two methods:
PLEASE NOTE:
*The text in the file here is a much simplified example. That is why I do not just use the output.append("\n\n"); in the second method. Also the \ns in the file are not always at the END of the line i.e. a line n the file could be Stipulation 1.1\nUnder this Stipulation...etc. *
The \n's in the file need to work. Also both JOptionPane.showMessageDialog(null,rules); and System.out.println(rules); give the same formatted output
Text in File:
A\n
B\n
C\n
D\n
Method 1:
private static void setGameRules(File f) throws FileNotFoundException, IOException
{
rules = Files.readAllLines(f.toPath(), Charset.defaultCharset());
JOptionPane.showMessageDialog(null,rules);
}
Output 1:
A\nB\nC\nD\n
Method 2:
private static void setGameRules(File f) throws FileNotFoundException, IOException
{
rules = Files.readAllLines(f.toPath(), Charset.defaultCharset());
StringBuilder output = new StringBuilder();
for (String s : rules)
{
output.append(s);
output.append("\n\n");//these \n work but the ones in my file do not
}
System.out.println(output);
}
Output 2:
A\n
B\n
C\n
D\n
The character sequence \n is simply a human readable representation of an unprintable character.
When reading it from a file, you get two characters a '\' and an 'n', not the line break character.
As such, you'll need to replace the placeholders in your file with a 'real' line break character.
Using the method I mentioned earlier: s = s.replaceAll( "\\\\n", System.lineSeparator() ); is one way, I'm sure there are others.
Perhaps in readAllLines you can add add the above line of code to do the replacement before, or as, you stick the line in the rules array.
Edit:
The reason this doesn't work the way you expect is because you're reading it from a file. If it was hardcoded into your class, the compiler would see the '\n' sequence and say "Oh boy! A line separator! I'll just replace that with (char)0x0A".
What do you mean with "it is not working"? In what way are they not working? Do you expect to see a line break? I am not sure if you actually have the characters '\n' at the end of each line, or the LineFeed Character (0x0A). The reason your '\n' would work in the Javas source is, that this is a way to escape the linefeed character. Tell us a little about your input file, how is it generated?
Second thing I notice is, that you print the text to the console in the second Method. I am not certain, that the JOptionPane will even display line breaks this way. I think it uses a JLabel, see Java: Linebreaks in JLabels? for that. The console does interpret \n as a linebreak.
The final Answer looks like this:
private static void setGameRules(File f) throws FileNotFoundException, IOException {
rules = Files.readAllLines(f.toPath(), Charset.defaultCharset());
for(int i =0;i!=rules.size();i++){
rules.set(i, rules.get(i).replaceAll( "\\\\n","\n"));
}
}
As #Ray said the \n in the file was just being read as chars \ and n not as the line seperator \n
I just added a for-loop to run through the list and replace them using:
rules.set(i, rules.get(i).replaceAll( "\\\\n","\n")
So, using something like:
for (int i = 0; i < files.length; i++) {
if (!files[i].isDirectory() && files[i].canRead()) {
try {
Scanner scan = new Scanner(files[i]);
System.out.println("Generating Categories for " + files[i].toPath());
while (scan.hasNextLine()) {
count++;
String line = scan.nextLine();
System.out.println(" ->" + line);
line = line.split("\t", 2)[1];
System.out.println("!- " + line);
JsonParser parser = new JsonParser();
JsonObject object = parser.parse(line).getAsJsonObject();
Set<Entry<String, JsonElement>> entrySet = object.entrySet();
exploreSet(entrySet);
}
scan.close();
// System.out.println(keyset);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
}
as one goes over a Hadoop output file, one of the JSON objects in the middle is breaking... because scan.nextLine() is not fetching the whole line before it brings it to split. ie, the output is:
->0 {"Flags":"0","transactions":{"totalTransactionAmount":"0","totalQuantitySold":"0"},"listingStatus":"NULL","conditionRollupId":"0","photoDisplayType":"0","title":"NULL","quantityAvailable":"0","viewItemCount":"0","visitCount":"0","itemCountryId":"0","itemAspects":{ ... "sellerSiteId":"0","siteId":"0","pictureUrl":"http://somewhere.com/45/x/AlphaNumeric/$(KGrHqR,!rgF!6n5wJSTBQO-G4k(Ww~~
!- {"Flags":"0","transactions":{"totalTransactionAmount":"0","totalQuantitySold":"0"},"listingStatus":"NULL","conditionRollupId":"0","photoDisplayType":"0","title":"NULL","quantityAvailable":"0","viewItemCount":"0","visitCount":"0","itemCountryId":"0","itemAspects":{ ... "sellerSiteId":"0","siteId":"0","pictureUrl":"http://somewhere.com/45/x/AlphaNumeric/$(KGrHqR,!rgF!6n5wJSTBQO-G4k(Ww~~
Most of the above data has been sanitized (not the URL (for the most part) however... )
and the URL continues as:
$(KGrHqZHJCgFBsO4dC3MBQdC2)Y4Tg~~60_1.JPG?set_id=8800005007
in the file....
So its slightly miffing.
This also is entry #112, and I have had other files parse without errors... but this one is screwing with my mind, mostly because I dont see how scan.nextLine() isnt working...
By debug output, the JSON error is caused by the string not being split properly.
And almost forgot, it also works JUST FINE if I attempt to put the offending line in its own file and parse just that.
EDIT:
Also blows up if I remove the offending line in about the same place.
Attempted with JVM 1.6 and 1.7
Workaround Solution:
BufferedReader scan = new BufferedReader(new FileReader(files[i]));
instead of scanner....
Based on your code, the best explanation I can come up with is that the line really does end after the "~~" according to the criteria used by Scanner.nextLine().
The criteria for an end-of-line are:
Something that matches this regex: "\r\n|[\n\r\u2028\u2029\u0085]" or
The end of the input stream
You say that the file continues after the "~~", so lets put EOF aside, and look at the regex. That will match any of the following:
The usual line separators:
<CR>
<NL>
<CR><NL>
... and three unusual forms of line separator that Scanner also recognizes.
0x0085 is the <NEL> or "next line" control code in the "ISO C1 Control" group
0x2028 is the Unicode "line separator" character
0x2029 is the Unicode "paragraph separator" character
My theory is that you've got one of the "unusual" forms in your input file, and this is not showing up in .... whatever tool it is that you are using to examine the files.
I suggest that you examine the input file using a tool that can show you the actual bytes of the file; e.g. the od utility on a Linux / Unix system. Also, check that this isn't caused by some kind of character encoding mismatch ... or trying to read or write binary data as text.
If these don't help, then the next step should be to run your application using your IDE's Java debugger, and single-step it through the Scanner.hasNextLine() and nextLine() calls to find out what the code is actually doing.
And almost forgot, it also works JUST FINE if I attempt to put the offending line in its own file and parse just that.
That's interesting. But if the tool you are using to extract the line is the same one that is not showing the (hypothesized) unusual line separator, then this evidence is not reliable. The process of extraction may be altering the "stuff" that is causing the problems.