From 0c81d815aaa6819dd6c45453590e08a918f1d580 Mon Sep 17 00:00:00 2001 From: artem Date: Sun, 7 Mar 2021 13:31:37 +0300 Subject: [PATCH 1/6] refactor --- Parser.java | 75 +++++++++++++++++++++++++++++++---------------------- 1 file changed, 44 insertions(+), 31 deletions(-) diff --git a/Parser.java b/Parser.java index c13a9fe..9156bb4 100644 --- a/Parser.java +++ b/Parser.java @@ -1,46 +1,59 @@ -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; +import java.io.*; +import java.nio.charset.StandardCharsets; +import java.util.concurrent.locks.ReadWriteLock; +import java.util.concurrent.locks.ReentrantReadWriteLock; /** * This class is thread safe. */ public class Parser { - private File file; - public synchronized void setFile(File f) { - file = f; + private final int BUFFER_SIZE = 4096; + private final File file; + private final ReadWriteLock readWriteLock = new ReentrantReadWriteLock(); + public Parser(File file) { + this.file = file; } - public synchronized File getFile() { + public File getFile() { return file; } public String getContent() throws IOException { - FileInputStream i = new FileInputStream(file); - String output = ""; - int data; - while ((data = i.read()) > 0) { - output += (char) data; - } - return output; + return read(false); } public String getContentWithoutUnicode() throws IOException { - FileInputStream i = new FileInputStream(file); - String output = ""; - int data; - while ((data = i.read()) > 0) { - if (data < 0x80) { - output += (char) data; - } + return read(true); + } + public String read(final boolean withoutUnicode) throws IOException { + readWriteLock.readLock().lock(); + try (BufferedReader reader = new BufferedReader(new FileReader((file)))) { + StringBuilder sb = new StringBuilder(file.length() < Integer.MAX_VALUE? (int) file.length(): Integer.MAX_VALUE); + char[] readBuffer = new char[BUFFER_SIZE]; + int sbIndex = 0; + int read; + do { + read = reader.read(readBuffer); + if (read > 0) { + if (withoutUnicode) { + for (int i = 0; i < read; i++) { + char c = readBuffer[i]; + if (c < 0x80) { + sb.insert(sbIndex++, c); + } + } + } else { + sb.append(readBuffer, 0, read); + } + } + } while (read > 0); + return sb.toString(); + } finally { + readWriteLock.readLock().unlock(); } - return output; } - public void saveContent(String content) { - FileOutputStream o = new FileOutputStream(file); - try { - for (int i = 0; i < content.length(); i += 1) { - o.write(content.charAt(i)); - } - } catch (IOException e) { - e.printStackTrace(); + public void saveContent(String content) throws IOException { + readWriteLock.writeLock().lock(); + try (FileOutputStream o = new FileOutputStream(file)) { + o.write(content.getBytes(StandardCharsets.UTF_8)); + } finally { + readWriteLock.writeLock().unlock(); } } } From 4d1d4bbefb841225167db96345eed722195c069c Mon Sep 17 00:00:00 2001 From: artem Date: Tue, 9 Mar 2021 03:55:34 +0300 Subject: [PATCH 2/6] keep contract --- Parser.java | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/Parser.java b/Parser.java index 9156bb4..193af09 100644 --- a/Parser.java +++ b/Parser.java @@ -7,13 +7,15 @@ */ public class Parser { private final int BUFFER_SIZE = 4096; - private final File file; private final ReadWriteLock readWriteLock = new ReentrantReadWriteLock(); - public Parser(File file) { + private File file; + public void setFile(File file) { + readWriteLock.writeLock().lock(); this.file = file; + readWriteLock.writeLock().unlock(); } public File getFile() { - return file; + return file; } public String getContent() throws IOException { return read(false); @@ -24,7 +26,13 @@ public String getContentWithoutUnicode() throws IOException { public String read(final boolean withoutUnicode) throws IOException { readWriteLock.readLock().lock(); try (BufferedReader reader = new BufferedReader(new FileReader((file)))) { - StringBuilder sb = new StringBuilder(file.length() < Integer.MAX_VALUE? (int) file.length(): Integer.MAX_VALUE); + long fileLength = file.length(); + if (fileLength > Integer.MAX_VALUE) { + throw new IOException("File is too big for String, " + fileLength + " bytes."); + } else if (fileLength == 0) { + return ""; + } + StringBuilder sb = new StringBuilder((int) fileLength); char[] readBuffer = new char[BUFFER_SIZE]; int sbIndex = 0; int read; From 5bf8a8b85445d2a80aaa73a908de0dd04190dfee Mon Sep 17 00:00:00 2001 From: artem Date: Tue, 9 Mar 2021 03:57:00 +0300 Subject: [PATCH 3/6] formatting --- Parser.java | 115 ++++++++++++++++++++++++++++------------------------ 1 file changed, 61 insertions(+), 54 deletions(-) diff --git a/Parser.java b/Parser.java index 193af09..0a3eb1e 100644 --- a/Parser.java +++ b/Parser.java @@ -2,66 +2,73 @@ import java.nio.charset.StandardCharsets; import java.util.concurrent.locks.ReadWriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock; + /** * This class is thread safe. */ public class Parser { - private final int BUFFER_SIZE = 4096; - private final ReadWriteLock readWriteLock = new ReentrantReadWriteLock(); - private File file; - public void setFile(File file) { - readWriteLock.writeLock().lock(); - this.file = file; - readWriteLock.writeLock().unlock(); - } - public File getFile() { - return file; - } - public String getContent() throws IOException { - return read(false); - } - public String getContentWithoutUnicode() throws IOException { - return read(true); - } - public String read(final boolean withoutUnicode) throws IOException { - readWriteLock.readLock().lock(); - try (BufferedReader reader = new BufferedReader(new FileReader((file)))) { - long fileLength = file.length(); - if (fileLength > Integer.MAX_VALUE) { - throw new IOException("File is too big for String, " + fileLength + " bytes."); - } else if (fileLength == 0) { - return ""; - } - StringBuilder sb = new StringBuilder((int) fileLength); - char[] readBuffer = new char[BUFFER_SIZE]; - int sbIndex = 0; - int read; - do { - read = reader.read(readBuffer); - if (read > 0) { - if (withoutUnicode) { - for (int i = 0; i < read; i++) { - char c = readBuffer[i]; - if (c < 0x80) { - sb.insert(sbIndex++, c); - } + private final int BUFFER_SIZE = 4096; + private final ReadWriteLock readWriteLock = new ReentrantReadWriteLock(); + private File file; + + public void setFile(File file) { + readWriteLock.writeLock().lock(); + this.file = file; + readWriteLock.writeLock().unlock(); + } + + public File getFile() { + return file; + } + + public String getContent() throws IOException { + return read(false); + } + + public String getContentWithoutUnicode() throws IOException { + return read(true); + } + + public String read(final boolean withoutUnicode) throws IOException { + readWriteLock.readLock().lock(); + try (BufferedReader reader = new BufferedReader(new FileReader((file)))) { + long fileLength = file.length(); + if (fileLength > Integer.MAX_VALUE) { + throw new IOException("File is too big for String, " + fileLength + " bytes."); + } else if (fileLength == 0) { + return ""; } - } else { - sb.append(readBuffer, 0, read); - } + StringBuilder sb = new StringBuilder((int) fileLength); + char[] readBuffer = new char[BUFFER_SIZE]; + int sbIndex = 0; + int read; + do { + read = reader.read(readBuffer); + if (read > 0) { + if (withoutUnicode) { + for (int i = 0; i < read; i++) { + char c = readBuffer[i]; + if (c < 0x80) { + sb.insert(sbIndex++, c); + } + } + } else { + sb.append(readBuffer, 0, read); + } + } + } while (read > 0); + return sb.toString(); + } finally { + readWriteLock.readLock().unlock(); } - } while (read > 0); - return sb.toString(); - } finally { - readWriteLock.readLock().unlock(); } - } - public void saveContent(String content) throws IOException { - readWriteLock.writeLock().lock(); - try (FileOutputStream o = new FileOutputStream(file)) { - o.write(content.getBytes(StandardCharsets.UTF_8)); - } finally { - readWriteLock.writeLock().unlock(); + + public void saveContent(String content) throws IOException { + readWriteLock.writeLock().lock(); + try (FileOutputStream o = new FileOutputStream(file)) { + o.write(content.getBytes(StandardCharsets.UTF_8)); + } finally { + readWriteLock.writeLock().unlock(); + } } - } } From 79be222e570d224bf1774e57bdd37e87509f19b4 Mon Sep 17 00:00:00 2001 From: artem Date: Fri, 12 Mar 2021 01:35:58 +0300 Subject: [PATCH 4/6] fix visibility with volatile --- Parser.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Parser.java b/Parser.java index 0a3eb1e..4d2f352 100644 --- a/Parser.java +++ b/Parser.java @@ -9,7 +9,7 @@ public class Parser { private final int BUFFER_SIZE = 4096; private final ReadWriteLock readWriteLock = new ReentrantReadWriteLock(); - private File file; + private volatile File file; public void setFile(File file) { readWriteLock.writeLock().lock(); From 7731c2f7798f1bffafc88c922e857cf870013248 Mon Sep 17 00:00:00 2001 From: artem Date: Sun, 4 Apr 2021 18:55:37 +0300 Subject: [PATCH 5/6] handle interrupions --- Parser.java | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/Parser.java b/Parser.java index 4d2f352..a4a5d27 100644 --- a/Parser.java +++ b/Parser.java @@ -7,7 +7,8 @@ * This class is thread safe. */ public class Parser { - private final int BUFFER_SIZE = 4096; + private final int READ_BUFFER_SIZE = 4096; + private final int WRITE_BUFFER_SIZE = 4096; private final ReadWriteLock readWriteLock = new ReentrantReadWriteLock(); private volatile File file; @@ -21,15 +22,15 @@ public File getFile() { return file; } - public String getContent() throws IOException { + public String getContent() throws IOException, InterruptedException { return read(false); } - public String getContentWithoutUnicode() throws IOException { + public String getContentWithoutUnicode() throws IOException, InterruptedException { return read(true); } - public String read(final boolean withoutUnicode) throws IOException { + public String read(final boolean withoutUnicode) throws IOException, InterruptedException { readWriteLock.readLock().lock(); try (BufferedReader reader = new BufferedReader(new FileReader((file)))) { long fileLength = file.length(); @@ -39,7 +40,7 @@ public String read(final boolean withoutUnicode) throws IOException { return ""; } StringBuilder sb = new StringBuilder((int) fileLength); - char[] readBuffer = new char[BUFFER_SIZE]; + char[] readBuffer = new char[READ_BUFFER_SIZE]; int sbIndex = 0; int read; do { @@ -56,6 +57,9 @@ public String read(final boolean withoutUnicode) throws IOException { sb.append(readBuffer, 0, read); } } + if (Thread.currentThread().isInterrupted()) { + throw new InterruptedException("File was not read"); + } } while (read > 0); return sb.toString(); } finally { @@ -63,10 +67,17 @@ public String read(final boolean withoutUnicode) throws IOException { } } - public void saveContent(String content) throws IOException { + public void saveContent(String content) throws IOException, InterruptedException { readWriteLock.writeLock().lock(); try (FileOutputStream o = new FileOutputStream(file)) { - o.write(content.getBytes(StandardCharsets.UTF_8)); + byte[] contentBytes = content.getBytes(StandardCharsets.UTF_8); + for (int i = 0; i < (contentBytes.length + 1) / WRITE_BUFFER_SIZE; i++) { + int offset = Math.min(contentBytes.length - i * WRITE_BUFFER_SIZE, WRITE_BUFFER_SIZE); + o.write(contentBytes, i * WRITE_BUFFER_SIZE, i * WRITE_BUFFER_SIZE + offset); + if (Thread.currentThread().isInterrupted()) { + throw new InterruptedException("File was not written"); + } + } } finally { readWriteLock.writeLock().unlock(); } From 292e7d7983f292cbd14d5a4093263aeade51c94b Mon Sep 17 00:00:00 2001 From: artem Date: Sun, 4 Apr 2021 19:03:57 +0300 Subject: [PATCH 6/6] fix write to file --- Parser.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Parser.java b/Parser.java index a4a5d27..b71743b 100644 --- a/Parser.java +++ b/Parser.java @@ -71,7 +71,7 @@ public void saveContent(String content) throws IOException, InterruptedException readWriteLock.writeLock().lock(); try (FileOutputStream o = new FileOutputStream(file)) { byte[] contentBytes = content.getBytes(StandardCharsets.UTF_8); - for (int i = 0; i < (contentBytes.length + 1) / WRITE_BUFFER_SIZE; i++) { + for (int i = 0; i < (contentBytes.length + WRITE_BUFFER_SIZE - 1) / WRITE_BUFFER_SIZE; i++) { int offset = Math.min(contentBytes.length - i * WRITE_BUFFER_SIZE, WRITE_BUFFER_SIZE); o.write(contentBytes, i * WRITE_BUFFER_SIZE, i * WRITE_BUFFER_SIZE + offset); if (Thread.currentThread().isInterrupted()) {