-1

following the question I asked before How to have my java project to use some files without using their absolute path? I found the solution but another problem popped up in creating text files that I want to write into.here's my code:

private String pathProvider() throws Exception {
    //finding the location where the jar file has been located
    String jarPath=URLDecoder.decode(getClass().getProtectionDomain().getCodeSource().getLocation().getPath(), "UTF-8");
    //creating the full and final path
    String completePath=jarPath.substring(0,jarPath.lastIndexOf("/"))+File.separator+"Records.txt";
    
    return completePath;
}

public void writeRecord() {
    
    try(Formatter writer=new Formatter(new FileWriter(new File(pathProvider()),true))) {
        
        writer.format("%s  %s  %s  %s  %s  %s  %s  %s  %n", whichIsChecked(),nameInput.getText(),lastNameInput.getText()
                ,idInput.getText(),fieldOfStudyInput.getText(),date.getSelectedItem().toString()
                ,month.getSelectedItem().toString(),year.getSelectedItem().toString());
        
        successful();
        
    } catch (Exception e) {
        failure();
    }
}

this works and creates the text file wherever the jar file is running from but my problem is that when the information is been written to the file, the numbers,symbols, and English characters are remained but other characters which are in Persian are turned into question marks. like: ????? 111 ????? ????.although running the app in eclipse doesn't make this problem,running the jar does. Note:I found the code ,inside pathProvider method, in some person's question.

Navid Nasro
  • 19
  • 1
  • 6
  • You can't write to resources. They are read only. You can write to files in the file system. Put them off the user's home directory – g00se Jul 25 '21 at 12:16
  • You will need to put the code you are running in your question. – tgdavies Jul 25 '21 at 12:27
  • @tgdavies this piece of code is causing the problem not the rest of the program. – Navid Nasro Jul 25 '21 at 12:37
  • As @rzwitserloot says in his answer, if your problem is what characters are written to the file, why do you think that how you create the path is the problem? – tgdavies Jul 25 '21 at 12:43
  • @tgdavies i don't know and i'm not sure but with absolute path everything works fine and I thought maybe its the encoding i passed that is causing question marks but seems it is not. – Navid Nasro Jul 25 '21 at 12:57

1 Answers1

0

Your pasted code and the linked question are complete red herrings - they have nothing whatsoever to do with the error you ran into. Also, that protection domain stuff is a hack and you've been told before not to write data files next to your jar files, it's not how OSes (are supposed to) work. Use user.home for this.

There is nothing in this method that explains the question marks - the string, as returned, has plenty of issues (see above), but NOT that it will result in question marks in the output.

Files are fundamentally bytes. Strings are fundamentally characters. Therefore, when you write code that writes a string to a file, some code somewhere is converting chars to bytes.

Make sure the place where that happens includes a charset encoding.

Use the new API (I think you've also been told to do this, by me, in an earlier question of yours) which defaults to UTF-8. Alternatively, specify UTF-8 when you write. Note that the usage of UTF-8 here is about the file name, not the contents of it (as in, if you put persian symbols in the file name, it's not about persian symbols in the contents of the file / in the contents you want to write).

Because you didn't paste the code, I can't give you specific details as there are hundreds of ways to do this, and I do not know which one you used.

To write to a file given a String representing its path:

Path p = Paths.get(completePath);
Files.write("Hello, World!", p);

is all you need. This will write as UTF_8, which can handle persian symbols (because the Files API defaults to UTF-8 if you specify no encoding, unlike e.g. new File, FileOutputStream, FileWriter, etc).

If you're using outdated APIs: new BufferedWriter(new OutputStreamWriter(new FileOutputStream(thePath), StandardCharsets.UTF-8) - but note that this is a resource leak bug unless you add the appropriate try-with-resources.

If you're using FileWriter: FileWriter is broken, never use this class. Use something else.

If you're converting the string on its own, it's str.getBytes(StandardCharsets.UTF_8), not str.getBytes().

rzwitserloot
  • 85,357
  • 5
  • 51
  • 72
  • now i added the code i used for writing into the file.everything worked fine before I add this method and yes I know what you said about `user.home` but it seemed better to me to have the file being created somewhere that the user would know and see the file and that would be where the jar is.even with this code right now it works when i run it in eclipse but why isn't the jar working that way? – Navid Nasro Jul 25 '21 at 12:53
  • As I said, do not use FileWriter. It is broken. – rzwitserloot Jul 25 '21 at 13:33
  • so if the problem is because of using FileWriter,then why with absolute path it's working fine? – Navid Nasro Jul 25 '21 at 16:36
  • It's not. You're running it on a different platform that has a different default encoding. Has nothing to do with absolute vs. relative path. FileWriter is broken because you can't specify an encoding (on newer java versions you can, but these have the java.nio.file API which is better. Why aren't you using that?) – rzwitserloot Jul 25 '21 at 19:33
  • yes, you're right. I really would like to thank you. the more we discuss the more I learn. the main reason that I was using `FileWriter` is to make the file appendable.right now I'm using `new BufferedWriter(new OutputStreamWriter(new FileOutputStream(thePath), StandardCharsets.UTF-8)` and question marks are disappeared but the file is not appendable. how can I work that out? – Navid Nasro Jul 26 '21 at 07:31
  • new API (by which I mean: 10 years ago, it was introduced - what you're using has been out of date about a decade now): `Files.write(thePath, theString, StandardOpenOption.APPEND)`. Or `Files.newBufferedWriter(thePath, StandardOpenOption.APPEND)` if you want a writer. No need for UTF-8 - Files defaults to it. outdated API: `new FileOutputStream(theFile, true)`, then wrap that in an OutputStreamWriter with UTF-8, and that in a BufferedWriter. (you do need UTF-8 here, the old API does NOT default to UTF_8 on its own) – rzwitserloot Jul 26 '21 at 12:32
  • thank you so much. sorry that I ask a lot but there's one more thing that I need to know and you pointed it out in your answer but I didn't get it. why using that `protection domain` and all the stuff I put here is not a good idea(you said it's a hack and it's better not to have the data files near jar)? and about `user.home`, where it's location ` will be on a computer using windows(for example)? – Navid Nasro Jul 27 '21 at 15:48
  • Because putting data next to code is bad. On all OSes, notably including windows since the past 20 years, you're not supposed to do that. On windows and the like, that directory is usually not writable (and if it is, your OS config is insecure and should be updated!) That protectiondomain stuff also doesn't work if you deploy your app in a module system, via the web, etc. – rzwitserloot Jul 27 '21 at 20:00