diff --git a/src/main/java/ninja/javafx/smartcsv/csv/CSVConfigurable.java b/src/main/java/ninja/javafx/smartcsv/csv/CSVConfigurable.java index 43c0830..ad4645b 100644 --- a/src/main/java/ninja/javafx/smartcsv/csv/CSVConfigurable.java +++ b/src/main/java/ninja/javafx/smartcsv/csv/CSVConfigurable.java @@ -35,6 +35,8 @@ public class CSVConfigurable { protected CsvPreference csvPreference; + protected String fileEncoding; + public CSVConfigurable() { csvPreference = CsvPreference.EXCEL_NORTH_EUROPE_PREFERENCE; } @@ -42,4 +44,9 @@ public class CSVConfigurable { public void setCsvPreference(CsvPreference csvPreference) { this.csvPreference = csvPreference; } + + public void setFileEncoding(String fileEncoding) { + this.fileEncoding = fileEncoding; + } + } diff --git a/src/main/java/ninja/javafx/smartcsv/csv/CSVFileReader.java b/src/main/java/ninja/javafx/smartcsv/csv/CSVFileReader.java index 4ccfac3..25911d7 100644 --- a/src/main/java/ninja/javafx/smartcsv/csv/CSVFileReader.java +++ b/src/main/java/ninja/javafx/smartcsv/csv/CSVFileReader.java @@ -34,6 +34,7 @@ import org.supercsv.io.ICsvMapReader; import java.io.File; import java.io.IOException; +import java.nio.charset.Charset; import java.util.Map; /** @@ -48,7 +49,8 @@ public class CSVFileReader extends CSVConfigurable implements FileReader currentCsvFile = new FileStorage<>(csvFileReader, csvFileWriter); private FileStorage currentConfigFile = new FileStorage<>(new ValidationFileReader(), new ValidationFileWriter()); private FileStorage csvPreferenceFile = new FileStorage<>(new PreferencesFileReader(), new PreferencesFileWriter()); + private FileStorage fileEncodingFile = new FileStorage<>(new EncodingFileReader(), new EncodingFileWriter()); private ListChangeListener errorListListener = c -> tableView.refresh(); private WeakListChangeListener weakErrorListListener = new WeakListChangeListener<>(errorListListener); @@ -238,10 +246,25 @@ public class SmartCSVController extends FXMLController { bindConfigFileName(); csvPreferenceFile.setFile(PREFERENCES_FILE); + fileEncodingFile.setFile(ENCODING_FILE); loadCsvPreferencesFromFile(); } + private void loadEncodingFromFile() { + if (fileEncodingFile.getFile().exists()) { + useLoadFileService(fileEncodingFile, event -> setFileEncoding(fileEncodingFile.getContent())); + } else { + setFileEncoding(Charset.defaultCharset().name()); + } + } + + private void setFileEncoding(String content) { + preferencesController.setFileEncoding(content); + csvFileReader.setFileEncoding(content); + csvFileWriter.setFileEncoding(content); + } + private void setupErrorSideBar(ResourceBundle resourceBundle) { errorSideBar = new ErrorSideBar(resourceBundle); errorSideBar.selectedValidationErrorProperty().addListener((observable, oldValue, newValue) -> { @@ -345,8 +368,29 @@ public class SmartCSVController extends FXMLController { CsvPreference csvPreference = preferencesController.getCsvPreference(); setCsvPreference(csvPreference); saveCsvPreferences(csvPreference); + String fileEncoding = CharsetHelper.getCharsetName(preferencesController.getFileEncoding()); + setFileEncoding(fileEncoding); + saveFileEncoding(fileEncoding); } else { preferencesController.setCsvPreference(csvPreferenceFile.getContent()); + preferencesController.setFileEncoding(fileEncodingFile.getContent()); + } + } + + private void saveFileEncoding(String fileEncoding) { + try { + createFileEncodingFile(); + fileEncodingFile.setContent(fileEncoding); + useSaveFileService(fileEncodingFile); + } catch (IOException e) { + e.printStackTrace(); + } + } + + private void createFileEncodingFile() throws IOException { + if (!fileEncodingFile.getFile().exists()) { + createPreferencesFileFolder(); + fileEncodingFile.getFile().createNewFile(); } } @@ -492,9 +536,13 @@ public class SmartCSVController extends FXMLController { private void loadCsvPreferencesFromFile() { if (csvPreferenceFile.getFile().exists()) { - useLoadFileService(csvPreferenceFile, event -> setCsvPreference(csvPreferenceFile.getContent())); + useLoadFileService(csvPreferenceFile, event -> { + setCsvPreference(csvPreferenceFile.getContent()); + loadEncodingFromFile(); + }); } else { setCsvPreference(CsvPreference.EXCEL_NORTH_EUROPE_PREFERENCE); + loadEncodingFromFile(); } } diff --git a/src/main/java/ninja/javafx/smartcsv/fx/preferences/PreferencesController.java b/src/main/java/ninja/javafx/smartcsv/fx/preferences/PreferencesController.java index b5ac7b9..012bea3 100644 --- a/src/main/java/ninja/javafx/smartcsv/fx/preferences/PreferencesController.java +++ b/src/main/java/ninja/javafx/smartcsv/fx/preferences/PreferencesController.java @@ -39,6 +39,7 @@ import org.springframework.stereotype.Component; import org.supercsv.prefs.CsvPreference; import java.net.URL; +import java.nio.charset.Charset; import java.util.ResourceBundle; import java.util.function.UnaryOperator; @@ -66,6 +67,9 @@ public class PreferencesController extends FXMLController { @FXML private ComboBox quoteMode; + @FXML + private ComboBox fileEncoding; + private String endOfLineSymbols; private BooleanProperty valid = new SimpleBooleanProperty(true); @@ -80,6 +84,7 @@ public class PreferencesController extends FXMLController { @Override public void initialize(URL location, ResourceBundle resources) { quoteMode.getItems().addAll("normal", "always", "column"); + fileEncoding.getItems().addAll(Charset.availableCharsets().keySet()); UnaryOperator allowOnlyOneCharacter = change -> { if (change.isContentChange()) { @@ -117,6 +122,14 @@ public class PreferencesController extends FXMLController { .build(); } + public void setFileEncoding(String fileEncoding) { + this.fileEncoding.setValue(fileEncoding); + } + + public String getFileEncoding() { + return fileEncoding.getValue(); + } + public boolean getValid() { return valid.get(); } diff --git a/src/main/java/ninja/javafx/smartcsv/preferences/CharsetHelper.java b/src/main/java/ninja/javafx/smartcsv/preferences/CharsetHelper.java new file mode 100644 index 0000000..c6136bf --- /dev/null +++ b/src/main/java/ninja/javafx/smartcsv/preferences/CharsetHelper.java @@ -0,0 +1,44 @@ +/* + The MIT License (MIT) + ----------------------------------------------------------------------------- + + Copyright (c) 2015-2016 javafx.ninja + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + +*/ + +package ninja.javafx.smartcsv.preferences; + +import java.nio.charset.Charset; + +/** + * Helper class for getting charset's name + */ +public class CharsetHelper { + + public static String getCharsetName(String name) { + try { + return Charset.forName(name).name(); + } catch (Exception e) { + return Charset.defaultCharset().name(); + } + } + +} diff --git a/src/main/java/ninja/javafx/smartcsv/preferences/EncodingFileReader.java b/src/main/java/ninja/javafx/smartcsv/preferences/EncodingFileReader.java new file mode 100644 index 0000000..08b867f --- /dev/null +++ b/src/main/java/ninja/javafx/smartcsv/preferences/EncodingFileReader.java @@ -0,0 +1,62 @@ +/* + The MIT License (MIT) + ----------------------------------------------------------------------------- + + Copyright (c) 2015-2016 javafx.ninja + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + +*/ + +package ninja.javafx.smartcsv.preferences; + +import com.google.gson.GsonBuilder; +import ninja.javafx.smartcsv.FileReader; + +import java.io.File; +import java.io.IOException; +import java.nio.charset.Charset; +import java.util.HashMap; +import java.util.Map; + +/** + * file reader for the file encoding + */ +public class EncodingFileReader implements FileReader { + + private String fileEncoding; + + public EncodingFileReader() { + fileEncoding = Charset.defaultCharset().name(); + } + + @Override + public String getContent() { + return fileEncoding; + } + + @Override + public void read(File filename) throws IOException { + Map settings = new GsonBuilder().create().fromJson(new java.io.FileReader(filename), HashMap.class); + if (settings != null) { + fileEncoding = CharsetHelper.getCharsetName(settings.get("fileEncoding").toString()); + } + } + +} diff --git a/src/main/java/ninja/javafx/smartcsv/preferences/EncodingFileWriter.java b/src/main/java/ninja/javafx/smartcsv/preferences/EncodingFileWriter.java new file mode 100644 index 0000000..e8f7527 --- /dev/null +++ b/src/main/java/ninja/javafx/smartcsv/preferences/EncodingFileWriter.java @@ -0,0 +1,59 @@ +/* + The MIT License (MIT) + ----------------------------------------------------------------------------- + + Copyright (c) 2015-2016 javafx.ninja + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + +*/ + +package ninja.javafx.smartcsv.preferences; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import ninja.javafx.smartcsv.FileWriter; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.util.HashMap; +import java.util.Map; + +/** + * Save the file encoding to configuration file + */ +public class EncodingFileWriter implements FileWriter { + + private String fileEncoding; + + @Override + public void setContent(String fileEncoding) { + this.fileEncoding = fileEncoding; + } + + @Override + public void write(File filename) throws IOException { + Map encodings = new HashMap<>(); + encodings.put("fileEncoding", CharsetHelper.getCharsetName(fileEncoding)); + Gson gson = new GsonBuilder().setPrettyPrinting().create(); + Files.write(filename.toPath(), gson.toJson(encodings).getBytes()); + } + +} diff --git a/src/main/resources/ninja/javafx/smartcsv/fx/preferences/preferences.fxml b/src/main/resources/ninja/javafx/smartcsv/fx/preferences/preferences.fxml index bac9768..d688702 100644 --- a/src/main/resources/ninja/javafx/smartcsv/fx/preferences/preferences.fxml +++ b/src/main/resources/ninja/javafx/smartcsv/fx/preferences/preferences.fxml @@ -14,6 +14,7 @@ + diff --git a/src/main/resources/ninja/javafx/smartcsv/fx/smartcsv.properties b/src/main/resources/ninja/javafx/smartcsv/fx/smartcsv.properties index a3fe5e9..ebd13a4 100644 --- a/src/main/resources/ninja/javafx/smartcsv/fx/smartcsv.properties +++ b/src/main/resources/ninja/javafx/smartcsv/fx/smartcsv.properties @@ -41,6 +41,7 @@ preferences.delimiterChar = Delimiter character: preferences.ignoreEmptyLines = Ignore empty lines: preferences.surroundingSpacesNeedQuotes = Surrounding spaces need quotes: preferences.quoteMode = Quote mode: +preferences.fileEncoding = File encoding: # validaton messages validation.message.not.empty = should not be empty diff --git a/src/main/resources/ninja/javafx/smartcsv/fx/smartcsv_de.properties b/src/main/resources/ninja/javafx/smartcsv/fx/smartcsv_de.properties index 89addd2..9923fc9 100644 --- a/src/main/resources/ninja/javafx/smartcsv/fx/smartcsv_de.properties +++ b/src/main/resources/ninja/javafx/smartcsv/fx/smartcsv_de.properties @@ -50,6 +50,7 @@ preferences.delimiterChar = Trennzeichen: preferences.ignoreEmptyLines = Leere Zeilen ignorieren: preferences.surroundingSpacesNeedQuotes = Leerzeichen einfassen: preferences.quoteMode = Einfassungsmodus: +preferences.fileEncoding = Dateicodierung: # validaton messages validation.message.not.empty = Darf nicht leer sein. diff --git a/src/test/java/ninja/javafx/smartcsv/preferences/CharsetHelperTest.java b/src/test/java/ninja/javafx/smartcsv/preferences/CharsetHelperTest.java new file mode 100644 index 0000000..4e53d03 --- /dev/null +++ b/src/test/java/ninja/javafx/smartcsv/preferences/CharsetHelperTest.java @@ -0,0 +1,56 @@ +/* + The MIT License (MIT) + ----------------------------------------------------------------------------- + + Copyright (c) 2015-2016 javafx.ninja + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + +*/ + +package ninja.javafx.smartcsv.preferences; + +import org.junit.jupiter.api.Test; + +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; + +import static org.junit.jupiter.api.Assertions.*; + +public class CharsetHelperTest { + + @Test + public void getCharsetName_known_charset() { + String result = CharsetHelper.getCharsetName("UTF-16"); + assertEquals(StandardCharsets.UTF_16.name(), result); + } + + @Test + public void getCharsetName_unknown_charset() { + String result = CharsetHelper.getCharsetName("foobar"); + assertEquals(StandardCharsets.UTF_8.name(), result); + } + + @Test + public void getCharsetName_null_charset() { + String result = CharsetHelper.getCharsetName(null); + assertEquals(StandardCharsets.UTF_8.name(), result); + } + +}