From b1cbb707222cf847b17669c628327e71a7b88faa Mon Sep 17 00:00:00 2001 From: Bart Maertens Date: Wed, 7 Oct 2026 11:56:48 +0200 Subject: [PATCH] Create the parent folder of the target file in Change file encoding and read and write through VFS, fixes #8779 --- .../transforms/0120-change-file-encoding.hpl | 129 ++++++++++++++ .../files/change-file-encoding-utf8.txt | 3 + .../main-0120-change-file-encoding.hwf | 165 ++++++++++++++++++ .../ChangeFileEncoding.java | 36 ++-- .../ChangeFileEncodingData.java | 2 + 5 files changed, 321 insertions(+), 14 deletions(-) create mode 100644 integration-tests/transforms/0120-change-file-encoding.hpl create mode 100644 integration-tests/transforms/files/change-file-encoding-utf8.txt create mode 100644 integration-tests/transforms/main-0120-change-file-encoding.hwf diff --git a/integration-tests/transforms/0120-change-file-encoding.hpl b/integration-tests/transforms/0120-change-file-encoding.hpl new file mode 100644 index 00000000000..aef9e31deb2 --- /dev/null +++ b/integration-tests/transforms/0120-change-file-encoding.hpl @@ -0,0 +1,129 @@ + + + + + 0120-change-file-encoding + Y + + + + Normal + + + N + 1000 + 100 + - + 2026/10/04 09:00:00.000 + - + 2026/10/04 09:00:00.000 + + + + Write a UTF-8 file in ISO-8859-1 to a folder that does not exist yet, with Create parent folder enabled. + 128 + 16 + 400 + 27 + Noto Sans + 11 + N + N + 14 + 58 + 90 + 201 + 232 + 251 + 14 + 58 + 90 + + + + + get filenames + change file encoding + Y + + + + get filenames + GetVariable + + Y + + 1 + + none + + + + + -1 + filename + -1 + none + String + ${PROJECT_HOME}/files/change-file-encoding-utf8.txt + + + -1 + target_filename + -1 + none + String + ${java.io.tmpdir}/0120-change-file-encoding/sub/change-file-encoding-iso.txt + + + + + 128 + 160 + + + + change file encoding + ChangeFileEncoding + + Y + + 1 + + none + + + N + N + filename + target_filename + ISO-8859-1 + UTF-8 + Y + + + 400 + 160 + + + + + + diff --git a/integration-tests/transforms/files/change-file-encoding-utf8.txt b/integration-tests/transforms/files/change-file-encoding-utf8.txt new file mode 100644 index 00000000000..29abefce843 --- /dev/null +++ b/integration-tests/transforms/files/change-file-encoding-utf8.txt @@ -0,0 +1,3 @@ +café +naïve +résumé diff --git a/integration-tests/transforms/main-0120-change-file-encoding.hwf b/integration-tests/transforms/main-0120-change-file-encoding.hwf new file mode 100644 index 00000000000..bbeb742b7d8 --- /dev/null +++ b/integration-tests/transforms/main-0120-change-file-encoding.hwf @@ -0,0 +1,165 @@ + + + + main-0120-change-file-encoding + Y + + + + - + 2026/10/07 12:00:00.000 + - + 2026/10/07 12:00:00.000 + + + + + Start + + SPECIAL + + 1 + 12 + 60 + 0 + 0 + N + 0 + 1 + N + 80 + 80 + + + + delete target folder + + DELETE_FOLDERS + + N + success_if_no_errors + 10 + + + ${java.io.tmpdir}/0120-change-file-encoding + + + N + 240 + 80 + + + + 0120-change-file-encoding.hpl + + PIPELINE + + ${PROJECT_HOME}/0120-change-file-encoding.hpl + N + N + N + + + N + N + Basic + local + Y + N + + Y + + N + N + 432 + 80 + + + + target file exists? + + FILE_EXISTS + + ${java.io.tmpdir}/0120-change-file-encoding/sub/change-file-encoding-iso.txt + N + 640 + 80 + + + + Abort + + ABORT + + Change file encoding did not write the target file into a new folder + N + 640 + 224 + + + + + + Start + delete target folder + Y + Y + Y + + + delete target folder + 0120-change-file-encoding.hpl + Y + Y + N + + + 0120-change-file-encoding.hpl + target file exists? + Y + Y + N + + + 0120-change-file-encoding.hpl + Abort + Y + N + N + + + target file exists? + Abort + Y + N + N + + + delete target folder + Abort + Y + N + N + + + + + + diff --git a/plugins/transforms/changefileencoding/src/main/java/org/apache/hop/pipeline/transforms/changefileencoding/ChangeFileEncoding.java b/plugins/transforms/changefileencoding/src/main/java/org/apache/hop/pipeline/transforms/changefileencoding/ChangeFileEncoding.java index 6a107effad7..a45cae30006 100644 --- a/plugins/transforms/changefileencoding/src/main/java/org/apache/hop/pipeline/transforms/changefileencoding/ChangeFileEncoding.java +++ b/plugins/transforms/changefileencoding/src/main/java/org/apache/hop/pipeline/transforms/changefileencoding/ChangeFileEncoding.java @@ -19,10 +19,9 @@ import java.io.BufferedReader; import java.io.BufferedWriter; -import java.io.FileInputStream; -import java.io.FileOutputStream; import java.io.InputStreamReader; import java.io.OutputStreamWriter; +import org.apache.commons.vfs2.FileObject; import org.apache.commons.vfs2.FileType; import org.apache.hop.core.ResultFile; import org.apache.hop.core.exception.HopException; @@ -153,21 +152,22 @@ public boolean processRow() throws HopException { PKG, "ChangeFileEncoding.Error.SourceFileNotAFile", sourceFilename)); } - // create directory only if not exists - if (!data.sourceFile.getParent().exists()) { + data.targetFile = HopVfs.getFileObject(targetFilename, variables); + + // create the folder of the target file only if it does not exist + FileObject targetFolder = data.targetFile.getParent(); + if (!targetFolder.exists()) { if (meta.isCreateParentFolder()) { - data.sourceFile.getParent().createFolder(); + targetFolder.createFolder(); } else { throw new HopException( BaseMessages.getString( - PKG, - "ChangeFileEncoding.Error.ParentFolderNotExist", - data.sourceFile.getParent().toString())); + PKG, "ChangeFileEncoding.Error.ParentFolderNotExist", targetFolder.toString())); } } // Change file encoding - changeEncoding(sourceFilename, targetFilename); + changeEncoding(targetFilename); putRow(data.inputRowMeta, outputRow); // copy row to output rowset(s) @@ -209,7 +209,7 @@ public boolean processRow() throws HopException { return true; } - private void changeEncoding(String sourceFilename, String targetFilename) throws HopException { + private void changeEncoding(String targetFilename) throws HopException { BufferedWriter buffWriter = null; BufferedReader buffReader = null; @@ -218,13 +218,14 @@ private void changeEncoding(String sourceFilename, String targetFilename) throws buffWriter = new BufferedWriter( new OutputStreamWriter( - new FileOutputStream(targetFilename, false), data.targetEncoding)); + HopVfs.getOutputStream(data.targetFile, false), data.targetEncoding)); if (Utils.isEmpty(data.sourceEncoding)) { - buffReader = new BufferedReader(new InputStreamReader(new FileInputStream(sourceFilename))); + buffReader = + new BufferedReader(new InputStreamReader(HopVfs.getInputStream(data.sourceFile))); } else { buffReader = new BufferedReader( - new InputStreamReader(new FileInputStream(sourceFilename), data.sourceEncoding)); + new InputStreamReader(HopVfs.getInputStream(data.sourceFile), data.sourceEncoding)); } char[] cBuf = new char[8192]; @@ -258,7 +259,7 @@ private void changeEncoding(String sourceFilename, String targetFilename) throws ResultFile resultFile = new ResultFile( ResultFile.FILE_TYPE_GENERAL, - HopVfs.getFileObject(targetFilename, variables), + data.targetFile, getPipelineMeta().getName(), getTransformName()); resultFile.setComment( @@ -300,6 +301,13 @@ public void dispose() { // ignore } } + if (data.targetFile != null) { + try { + data.targetFile.close(); + } catch (Exception e) { + // ignore + } + } super.dispose(); } } diff --git a/plugins/transforms/changefileencoding/src/main/java/org/apache/hop/pipeline/transforms/changefileencoding/ChangeFileEncodingData.java b/plugins/transforms/changefileencoding/src/main/java/org/apache/hop/pipeline/transforms/changefileencoding/ChangeFileEncodingData.java index 52ed229a12e..4b5d65a08bf 100644 --- a/plugins/transforms/changefileencoding/src/main/java/org/apache/hop/pipeline/transforms/changefileencoding/ChangeFileEncodingData.java +++ b/plugins/transforms/changefileencoding/src/main/java/org/apache/hop/pipeline/transforms/changefileencoding/ChangeFileEncodingData.java @@ -27,6 +27,7 @@ public class ChangeFileEncodingData extends BaseTransformData implements ITransf public int indexOfFileename; public int indexOfTargetFileename; public FileObject sourceFile; + public FileObject targetFile; public String sourceEncoding; public String targetEncoding; @@ -38,6 +39,7 @@ public ChangeFileEncodingData() { indexOfFileename = -1; indexOfTargetFileename = -1; sourceFile = null; + targetFile = null; sourceEncoding = null; targetEncoding = null; }