Pārlūkot izejas kodu

Make ReverseFileReader use Paths.

Change-Id: I921a395e088846216650d1ac14207cb915a6bb8c
Reviewed-on: http://gerrit.dmdirc.com/4045
Automatic-Compile: DMDirc Build Manager
Reviewed-by: Chris Smith <chris@dmdirc.com>
changes/45/4045/3
Greg Holmes 9 gadus atpakaļ
vecāks
revīzija
87e3c1343d

+ 39
- 54
src/com/dmdirc/util/io/ReverseFileReader.java Parādīt failu

23
 package com.dmdirc.util.io;
23
 package com.dmdirc.util.io;
24
 
24
 
25
 import java.io.EOFException;
25
 import java.io.EOFException;
26
-import java.io.File;
27
 import java.io.IOException;
26
 import java.io.IOException;
28
-import java.io.RandomAccessFile;
27
+import java.nio.ByteBuffer;
28
+import java.nio.channels.SeekableByteChannel;
29
 import java.nio.charset.Charset;
29
 import java.nio.charset.Charset;
30
+import java.nio.file.Files;
31
+import java.nio.file.Path;
32
+import java.nio.file.StandardOpenOption;
30
 import java.util.ArrayList;
33
 import java.util.ArrayList;
31
 import java.util.Stack;
34
 import java.util.Stack;
32
 
35
 
35
  */
38
  */
36
 public class ReverseFileReader {
39
 public class ReverseFileReader {
37
 
40
 
41
+    /** Path to the file we're reading. */
42
+    private final Path file;
38
     /** File to manipulate. */
43
     /** File to manipulate. */
39
-    private RandomAccessFile file;
40
-
44
+    private SeekableByteChannel byteChannel;
41
     /** Number of bytes to skip backwards at a time. */
45
     /** Number of bytes to skip backwards at a time. */
42
     private byte seekLength = 50;
46
     private byte seekLength = 50;
43
 
47
 
44
     /**
48
     /**
45
      * Create a new ReverseFileReader.
49
      * Create a new ReverseFileReader.
46
      *
50
      *
47
-     * @param filename File to open.
48
-     * @throws SecurityException If a security manager exists and its checkRead method denies read access to the file.
49
-     * @throws IOException If there is an error seeking to the end of the file.
50
-     */
51
-    public ReverseFileReader(final String filename) throws SecurityException, IOException {
52
-        file = new RandomAccessFile(filename, "r");
53
-        reset();
54
-    }
55
-
56
-    /**
57
-     * Create a new ReverseFileReader.
51
+     * @param file File to read
58
      *
52
      *
59
-     * @param myFile Existing file to use.
60
-     * @throws SecurityException If a security manager exists and its checkRead method denies read access to the file.
53
+     * @throws SecurityException If a security manager exists and its checkRead method denies
54
+     * read access to the file.
61
      * @throws IOException If there is an error seeking to the end of the file.
55
      * @throws IOException If there is an error seeking to the end of the file.
62
      */
56
      */
63
-    public ReverseFileReader(final File myFile) throws SecurityException, IOException {
64
-        file = new RandomAccessFile(myFile, "r");
57
+    public ReverseFileReader(final Path file) throws SecurityException, IOException {
58
+        this.file = file;
59
+        byteChannel = Files.newByteChannel(file, StandardOpenOption.READ);
65
         reset();
60
         reset();
66
     }
61
     }
67
 
62
 
70
      *
65
      *
71
      * @throws IOException If there is an error seeking, or the file is closed.
66
      * @throws IOException If there is an error seeking, or the file is closed.
72
      */
67
      */
73
-    public void reset() throws IOException {
74
-        if (file == null) {
75
-            throw new IOException("File has been closed.");
68
+    public final void reset() throws IOException {
69
+        if (!byteChannel.isOpen()) {
70
+            throw new IOException("Channel has been closed.");
76
         }
71
         }
77
-        file.seek(file.length());
72
+        byteChannel = Files.newByteChannel(file, StandardOpenOption.READ);
73
+        byteChannel.position(byteChannel.size());
78
     }
74
     }
79
 
75
 
80
     /**
76
     /**
102
      * @throws IOException If there is an error closing the file, or if it has been closed already.
98
      * @throws IOException If there is an error closing the file, or if it has been closed already.
103
      */
99
      */
104
     public void close() throws IOException {
100
     public void close() throws IOException {
105
-        if (file == null) {
106
-            throw new IOException("File has been closed.");
101
+        if (!byteChannel.isOpen()) {
102
+            throw new IOException("Channel has been closed.");
107
         }
103
         }
108
-        file.close();
109
-        file = null;
104
+        byteChannel.close();
110
     }
105
     }
111
 
106
 
112
     /**
107
     /**
116
      * @throws IOException If an error reading or seeking occured, or if the fiel is closed.
111
      * @throws IOException If an error reading or seeking occured, or if the fiel is closed.
117
      */
112
      */
118
     public String getNextLine() throws IOException {
113
     public String getNextLine() throws IOException {
119
-        if (file == null) {
120
-            throw new IOException("File has been closed.");
114
+        if (!byteChannel.isOpen()) {
115
+            throw new IOException("Channel has been closed.");
121
         }
116
         }
122
         // Used to store result to output.
117
         // Used to store result to output.
123
-
124
         final ArrayList<Byte> line = new ArrayList<>(seekLength);
118
         final ArrayList<Byte> line = new ArrayList<>(seekLength);
125
-        // Used to store position in file pre-read
126
-        long fp;
127
-        // Used to store position in file when this is called
128
-        final long startfp;
129
-        // Used to store read bytes
130
-        byte[] bytes;
131
-        // Distance seeked
132
-        int seekDistance;
133
-
134
         // Check current position, if 0 we are at the start of the file
119
         // Check current position, if 0 we are at the start of the file
135
         // and should throw an exception.
120
         // and should throw an exception.
136
-        startfp = file.getFilePointer();
121
+        final long startfp = byteChannel.position();
137
         if (startfp == 0) {
122
         if (startfp == 0) {
138
             throw new EOFException("Reached Start of file");
123
             throw new EOFException("Reached Start of file");
139
         }
124
         }
140
 
125
 
141
         // Keep looping until we get a full line, or the end of the file
126
         // Keep looping until we get a full line, or the end of the file
142
         boolean keepLooping = true;
127
         boolean keepLooping = true;
143
-        boolean gotNewLine;
144
         while (keepLooping) {
128
         while (keepLooping) {
145
-            gotNewLine = false;
146
             // Get Current Position
129
             // Get Current Position
147
-            fp = file.getFilePointer();
130
+            long fp = byteChannel.position();
148
 
131
 
149
             // Check how far to seek backwards (seekLength or to the start of the file)
132
             // Check how far to seek backwards (seekLength or to the start of the file)
133
+            final int seekDistance;
150
             if (fp < seekLength) {
134
             if (fp < seekLength) {
151
                 // Seek to the start of the file;
135
                 // Seek to the start of the file;
152
                 seekDistance = (int) fp;
136
                 seekDistance = (int) fp;
154
             } else {
138
             } else {
155
                 // Seek to position current-seekLength
139
                 // Seek to position current-seekLength
156
                 seekDistance = seekLength;
140
                 seekDistance = seekLength;
157
-                fp = fp - seekDistance;
141
+                fp -= seekDistance;
158
             }
142
             }
159
             // Seek!
143
             // Seek!
160
-            file.seek(fp);
144
+            byteChannel.position(fp);
161
 
145
 
162
-            bytes = new byte[seekDistance];
146
+            final ByteBuffer bytes = ByteBuffer.allocate(seekDistance);
163
             // Read into the bytes array
147
             // Read into the bytes array
164
-            file.read(bytes);
148
+            byteChannel.read(bytes);
165
 
149
 
166
             // And loop looking for data
150
             // And loop looking for data
167
             // This uses seekDistance so that only wanted data is checked.
151
             // This uses seekDistance so that only wanted data is checked.
152
+            boolean gotNewLine = false;
168
             for (int i = seekDistance - 1; i >= 0; --i) {
153
             for (int i = seekDistance - 1; i >= 0; --i) {
169
                 // Check for New line Character, or a non carriage-return char
154
                 // Check for New line Character, or a non carriage-return char
170
-                if (bytes[i] == '\n') {
155
+                if (bytes.get(i) == '\n') {
171
                     // Seek to the location of this character and exit this loop.
156
                     // Seek to the location of this character and exit this loop.
172
-                    file.seek(fp + i);
157
+                    byteChannel.position(fp + i);
173
                     gotNewLine = true;
158
                     gotNewLine = true;
174
                     break;
159
                     break;
175
-                } else if (bytes[i] != '\r') {
160
+                } else if (bytes.get(i) != '\r') {
176
                     // Add to the result, the loop will continue going.
161
                     // Add to the result, the loop will continue going.
177
-                    line.add(0, bytes[i]);
162
+                    line.add(0, bytes.get(i));
178
                 }
163
                 }
179
             }
164
             }
180
 
165
 
186
                 // find a new line anywhere. no more loops are possible, so Treat
171
                 // find a new line anywhere. no more loops are possible, so Treat
187
                 // this as "got new line"
172
                 // this as "got new line"
188
                 gotNewLine = true;
173
                 gotNewLine = true;
189
-                file.seek(0);
174
+                byteChannel.position(0);
190
             }
175
             }
191
 
176
 
192
             // Do we need to continue?
177
             // Do we need to continue?
197
             } else {
182
             } else {
198
                 // We have not found a new line anywhere,
183
                 // We have not found a new line anywhere,
199
                 // Seek to the pre-read position, and repeat.
184
                 // Seek to the pre-read position, and repeat.
200
-                file.seek(fp);
185
+                byteChannel.position(fp);
201
             }
186
             }
202
 
187
 
203
         }
188
         }
240
         final StringBuilder result = new StringBuilder();
225
         final StringBuilder result = new StringBuilder();
241
         for (int i = 0; i < numLines; ++i) {
226
         for (int i = 0; i < numLines; ++i) {
242
             try {
227
             try {
243
-                result.insert(0, "\n");
228
+                result.insert(0, '\n');
244
                 result.insert(0, getNextLine());
229
                 result.insert(0, getNextLine());
245
             } catch (IOException e) {
230
             } catch (IOException e) {
246
                 break;
231
                 break;

+ 4
- 0
test-res/com/dmdirc/util/io/test5.txt Parādīt failu

1
+
2
+Line 1
3
+Line 2
4
+Line 3

+ 39
- 12
test/com/dmdirc/util/io/ReverseFileReaderTest.java Parādīt failu

22
 
22
 
23
 package com.dmdirc.util.io;
23
 package com.dmdirc.util.io;
24
 
24
 
25
-import java.io.File;
26
 import java.io.IOException;
25
 import java.io.IOException;
27
 import java.net.URISyntaxException;
26
 import java.net.URISyntaxException;
27
+import java.nio.file.Paths;
28
 import java.util.Stack;
28
 import java.util.Stack;
29
 
29
 
30
 import org.junit.Test;
30
 import org.junit.Test;
31
 
31
 
32
-import static org.junit.Assert.*;
32
+import static org.junit.Assert.assertEquals;
33
 
33
 
34
 public class ReverseFileReaderTest {
34
 public class ReverseFileReaderTest {
35
 
35
 
36
     @Test
36
     @Test
37
     public void testIndividual() throws IOException, URISyntaxException {
37
     public void testIndividual() throws IOException, URISyntaxException {
38
         final ReverseFileReader reader = new ReverseFileReader(
38
         final ReverseFileReader reader = new ReverseFileReader(
39
-                new File(getClass().getResource("test1.txt").toURI()));
39
+                Paths.get(getClass().getResource("test1.txt").toURI()));
40
         assertEquals("Line 7", reader.getNextLine());
40
         assertEquals("Line 7", reader.getNextLine());
41
         assertEquals("Line 6", reader.getNextLine());
41
         assertEquals("Line 6", reader.getNextLine());
42
         assertEquals("Line 5", reader.getNextLine());
42
         assertEquals("Line 5", reader.getNextLine());
50
     @Test
50
     @Test
51
     public void testCarriageReturn() throws IOException, URISyntaxException {
51
     public void testCarriageReturn() throws IOException, URISyntaxException {
52
         final ReverseFileReader reader = new ReverseFileReader(
52
         final ReverseFileReader reader = new ReverseFileReader(
53
-                new File(getClass().getResource("test4.txt").toURI()));
53
+                Paths.get((getClass().getResource("test4.txt").toURI())));
54
         reader.getNextLine();
54
         reader.getNextLine();
55
         assertEquals("Normal line", reader.getNextLine());
55
         assertEquals("Normal line", reader.getNextLine());
56
         reader.close();
56
         reader.close();
59
     @Test
59
     @Test
60
     public void testLongLine() throws IOException, URISyntaxException {
60
     public void testLongLine() throws IOException, URISyntaxException {
61
         final ReverseFileReader reader = new ReverseFileReader(
61
         final ReverseFileReader reader = new ReverseFileReader(
62
-                new File(getClass().getResource("test4.txt").toURI()));
62
+                Paths.get((getClass().getResource("test4.txt").toURI())));
63
         assertEquals("This is a line that is longer than 50 characters, so " +
63
         assertEquals("This is a line that is longer than 50 characters, so " +
64
                 "should cause the reader to have to scan back multiple times.",
64
                 "should cause the reader to have to scan back multiple times.",
65
                 reader.getNextLine());
65
                 reader.getNextLine());
69
     @Test
69
     @Test
70
     public void testStack() throws IOException, URISyntaxException {
70
     public void testStack() throws IOException, URISyntaxException {
71
         final ReverseFileReader reader = new ReverseFileReader(
71
         final ReverseFileReader reader = new ReverseFileReader(
72
-                new File(getClass().getResource("test1.txt").toURI()));
72
+                Paths.get((getClass().getResource("test1.txt").toURI())));
73
         final Stack<String> lines = reader.getLines(10);
73
         final Stack<String> lines = reader.getLines(10);
74
 
74
 
75
         assertEquals(7, lines.size());
75
         assertEquals(7, lines.size());
86
     @Test
86
     @Test
87
     public void testSmallStack() throws IOException, URISyntaxException {
87
     public void testSmallStack() throws IOException, URISyntaxException {
88
         final ReverseFileReader reader = new ReverseFileReader(
88
         final ReverseFileReader reader = new ReverseFileReader(
89
-                new File(getClass().getResource("test1.txt").toURI()));
89
+                Paths.get((getClass().getResource("test1.txt").toURI())));
90
         final Stack<String> lines = reader.getLines(3);
90
         final Stack<String> lines = reader.getLines(3);
91
 
91
 
92
         assertEquals(3, lines.size());
92
         assertEquals(3, lines.size());
96
         reader.close();
96
         reader.close();
97
     }
97
     }
98
 
98
 
99
+    @Test
100
+    public void testgetLinesAsString() throws IOException, URISyntaxException {
101
+        final ReverseFileReader reader = new ReverseFileReader(
102
+                Paths.get((getClass().getResource("test5.txt").toURI())));
103
+        final String lines = reader.getLinesAsString(3);
104
+        assertEquals("Line 1\nLine 2\nLine 3\n", lines);
105
+        reader.close();
106
+    }
107
+
108
+    @Test
109
+    public void testgetLinesAsStringLeadingNewline() throws IOException, URISyntaxException {
110
+        final ReverseFileReader reader = new ReverseFileReader(
111
+                Paths.get((getClass().getResource("test5.txt").toURI())));
112
+        final String lines = reader.getLinesAsString(4);
113
+        assertEquals("Line 1\nLine 2\nLine 3\n", lines);
114
+        reader.close();
115
+    }
116
+
117
+    @Test
118
+    public void testIllegalGetLinesAsString() throws IOException, URISyntaxException {
119
+        final ReverseFileReader reader = new ReverseFileReader(
120
+                Paths.get((getClass().getResource("test5.txt").toURI())));
121
+        reader.close();
122
+        final String lines = reader.getLinesAsString(4);
123
+        assertEquals("", lines);
124
+    }
125
+
99
     @Test
126
     @Test
100
     public void testReset() throws IOException, URISyntaxException {
127
     public void testReset() throws IOException, URISyntaxException {
101
         final ReverseFileReader reader = new ReverseFileReader(
128
         final ReverseFileReader reader = new ReverseFileReader(
102
-                new File(getClass().getResource("test1.txt").toURI()));
129
+                Paths.get((getClass().getResource("test1.txt").toURI())));
103
         assertEquals("Line 7", reader.getNextLine());
130
         assertEquals("Line 7", reader.getNextLine());
104
         assertEquals("Line 6", reader.getNextLine());
131
         assertEquals("Line 6", reader.getNextLine());
105
         reader.reset();
132
         reader.reset();
112
     @Test(expected=IOException.class)
139
     @Test(expected=IOException.class)
113
     public void testIllegalClose() throws URISyntaxException, IOException {
140
     public void testIllegalClose() throws URISyntaxException, IOException {
114
         final ReverseFileReader reader = new ReverseFileReader(
141
         final ReverseFileReader reader = new ReverseFileReader(
115
-                new File(getClass().getResource("test1.txt").toURI()));
142
+                Paths.get((getClass().getResource("test1.txt").toURI())));
116
         reader.close();
143
         reader.close();
117
         reader.close();
144
         reader.close();
118
     }
145
     }
120
     @Test(expected=IOException.class)
147
     @Test(expected=IOException.class)
121
     public void testIllegalReset() throws URISyntaxException, IOException {
148
     public void testIllegalReset() throws URISyntaxException, IOException {
122
         final ReverseFileReader reader = new ReverseFileReader(
149
         final ReverseFileReader reader = new ReverseFileReader(
123
-                new File(getClass().getResource("test1.txt").toURI()));
150
+                Paths.get((getClass().getResource("test1.txt").toURI())));
124
         reader.close();
151
         reader.close();
125
         reader.reset();
152
         reader.reset();
126
     }
153
     }
128
     @Test(expected=IOException.class)
155
     @Test(expected=IOException.class)
129
     public void testIllegalGetNextLine() throws URISyntaxException, IOException {
156
     public void testIllegalGetNextLine() throws URISyntaxException, IOException {
130
         final ReverseFileReader reader = new ReverseFileReader(
157
         final ReverseFileReader reader = new ReverseFileReader(
131
-                new File(getClass().getResource("test1.txt").toURI()));
158
+                Paths.get((getClass().getResource("test1.txt").toURI())));
132
         reader.close();
159
         reader.close();
133
         reader.getNextLine();
160
         reader.getNextLine();
134
     }
161
     }
136
     @Test
163
     @Test
137
     public void testSeekLength() throws IOException, URISyntaxException {
164
     public void testSeekLength() throws IOException, URISyntaxException {
138
         final ReverseFileReader reader = new ReverseFileReader(
165
         final ReverseFileReader reader = new ReverseFileReader(
139
-                new File(getClass().getResource("test1.txt").toURI()));
166
+                Paths.get((getClass().getResource("test1.txt").toURI())));
140
         reader.setSeekLength((byte) 100);
167
         reader.setSeekLength((byte) 100);
141
         assertEquals((byte) 100, reader.getSeekLength());
168
         assertEquals((byte) 100, reader.getSeekLength());
142
     }
169
     }

Notiek ielāde…
Atcelt
Saglabāt