Skip to content

Commit 2d9238e

Browse files
EcljpseB0Tjukzi
authored andcommitted
Provide API for IFile Bulk read/write of all bytes/String/chars
Convenience methods like java.nio.file.Files.readAllBytes(Path) etc. The new API could be used to substitute similar Util methods like org.eclipse.jdt.internal.core.util.Util.getResourceContentsAsCharArray (hotspot of jdt pasrsing) Searching the workspace like org.eclipse.search.internal.core.text.FileCharSequenceProvider.toShortString(IFile) is similar but not directly replaceable with this API. Note that clients currently do have to query file.getCharset() and file.getContents() separately, possible opening the file twice to identify the UTF-BOM while the new API combines both calls, which would allow platform to open the file single time. While this PR does not implements such optimizations it is already faster to use the JDKs bulk methods instead of streaming. Also this API avoids typical warnings of not closed Streams with the former stream api in client code.
1 parent 64f88ca commit 2d9238e

File tree

11 files changed

+507
-76
lines changed

11 files changed

+507
-76
lines changed

resources/bundles/org.eclipse.core.filesystem/META-INF/MANIFEST.MF

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ Manifest-Version: 1.0
22
Bundle-ManifestVersion: 2
33
Bundle-Name: %pluginName
44
Bundle-SymbolicName: org.eclipse.core.filesystem; singleton:=true
5-
Bundle-Version: 1.10.400.qualifier
5+
Bundle-Version: 1.11.0.qualifier
66
Bundle-Localization: plugin
77
Require-Bundle: org.eclipse.equinox.common;bundle-version="[3.18.0,4.0.0)",
88
org.eclipse.equinox.registry;bundle-version="[3.2.0,4.0.0)",

resources/bundles/org.eclipse.core.filesystem/src/org/eclipse/core/filesystem/IFileStore.java

Lines changed: 54 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,17 @@
1515
******************************************************************************/
1616
package org.eclipse.core.filesystem;
1717

18+
import java.io.IOException;
1819
import java.io.InputStream;
1920
import java.io.OutputStream;
2021
import java.net.URI;
2122
import org.eclipse.core.filesystem.provider.FileStore;
2223
import org.eclipse.core.internal.filesystem.FileStoreUtil;
23-
import org.eclipse.core.runtime.*;
24+
import org.eclipse.core.runtime.CoreException;
25+
import org.eclipse.core.runtime.IAdaptable;
26+
import org.eclipse.core.runtime.IPath;
27+
import org.eclipse.core.runtime.IProgressMonitor;
28+
import org.eclipse.core.runtime.Status;
2429

2530
/**
2631
* A file store is responsible for storage and retrieval of a single file in some file system.
@@ -412,6 +417,29 @@ public interface IFileStore extends IAdaptable {
412417
*/
413418
public InputStream openInputStream(int options, IProgressMonitor monitor) throws CoreException;
414419

420+
/**
421+
* Returns the bytes contents of this file. This method is not intended for reading in
422+
* large files that do not fit in a byte array. Preferable over calling
423+
* {@code openInputStream(options, monitor).readAllBytes()}
424+
* @param options bit-wise or of option flag constants (currently only {@link EFS#NONE}
425+
* is applicable).
426+
* @param monitor a progress monitor, or <code>null</code> if progress
427+
* reporting and cancellation are not desired
428+
* @return contents of this file as byte array.
429+
* @throws CoreException if this method fails.
430+
* @see #openInputStream(int, IProgressMonitor)
431+
* @since 1.11
432+
*/
433+
public default byte[] readAllBytes(int options, IProgressMonitor monitor) throws CoreException {
434+
// Default implementation is meant to be overridden for local files
435+
// as Files.readAllBytes is ~ 1.5 times faster
436+
try (InputStream stream = openInputStream(options, monitor)) {
437+
return stream.readAllBytes();
438+
} catch (IOException e) {
439+
throw new CoreException(Status.error("Error reading " + getName(), e)); //$NON-NLS-1$
440+
}
441+
}
442+
415443
/**
416444
* Returns an open output stream on the contents of this file. The number of
417445
* concurrently open streams depends on implementation and can be limited.
@@ -449,6 +477,31 @@ public interface IFileStore extends IAdaptable {
449477
*/
450478
public OutputStream openOutputStream(int options, IProgressMonitor monitor) throws CoreException;
451479

480+
/**
481+
* Writes the contents to this file.
482+
* <p>
483+
* The {@link EFS#APPEND} update flag controls where
484+
* output is written to the file. If this flag is specified, content written
485+
* to the stream will be appended to the end of the file. If this flag is
486+
* not specified, the contents of the existing file, if any, is truncated to zero
487+
* and the new output will be written from the start of the file.
488+
* </p>
489+
*
490+
* @param content contents given as byte array
491+
* @param options bit-wise or of option flag constants ({@link EFS#APPEND}).
492+
* @param monitor a progress monitor, or <code>null</code> if progress
493+
* reporting and cancellation are not desired
494+
* @see #openOutputStream(int, IProgressMonitor)
495+
* @since 1.11
496+
* **/
497+
public default void write(byte[] content, int options, IProgressMonitor monitor) throws CoreException {
498+
try (OutputStream out = openOutputStream(options, monitor)) {
499+
out.write(content);
500+
} catch (IOException e) {
501+
throw new CoreException(Status.error(e.getMessage(), e));
502+
}
503+
}
504+
452505
/**
453506
* Writes information about this file to the underlying file system. Only
454507
* certain parts of the file information structure can be written using this

resources/bundles/org.eclipse.core.filesystem/src/org/eclipse/core/internal/filesystem/local/LocalFile.java

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
import java.nio.file.FileAlreadyExistsException;
3232
import java.nio.file.Files;
3333
import java.nio.file.NoSuchFileException;
34+
import java.nio.file.StandardOpenOption;
3435
import org.eclipse.core.filesystem.EFS;
3536
import org.eclipse.core.filesystem.IFileInfo;
3637
import org.eclipse.core.filesystem.IFileStore;
@@ -447,6 +448,7 @@ private boolean isSameFile(File source, File destination) throws IOException {
447448
}
448449
}
449450

451+
/** @see #readAllBytes(int, IProgressMonitor) */
450452
@Override
451453
public InputStream openInputStream(int options, IProgressMonitor monitor) throws CoreException {
452454
try {
@@ -467,6 +469,28 @@ public InputStream openInputStream(int options, IProgressMonitor monitor) throws
467469
}
468470
}
469471

472+
/** @see #openInputStream(int, IProgressMonitor) */
473+
@Override
474+
public byte[] readAllBytes(int options, IProgressMonitor monitor) throws CoreException {
475+
try {
476+
return Files.readAllBytes(file.toPath());
477+
} catch (IOException e) {
478+
String message;
479+
if (!file.exists()) {
480+
message = NLS.bind(Messages.fileNotFound, filePath);
481+
Policy.error(EFS.ERROR_NOT_EXISTS, message, e);
482+
} else if (file.isDirectory()) {
483+
message = NLS.bind(Messages.notAFile, filePath);
484+
Policy.error(EFS.ERROR_WRONG_TYPE, message, e);
485+
} else {
486+
message = NLS.bind(Messages.couldNotRead, filePath);
487+
Policy.error(EFS.ERROR_READ, message, e);
488+
}
489+
return null;
490+
}
491+
}
492+
493+
/** @see #write(byte[], int, IProgressMonitor) */
470494
@Override
471495
public OutputStream openOutputStream(int options, IProgressMonitor monitor) throws CoreException {
472496
try {
@@ -486,6 +510,30 @@ public OutputStream openOutputStream(int options, IProgressMonitor monitor) thro
486510
}
487511
}
488512

513+
/** @see #openOutputStream(int, IProgressMonitor) */
514+
@Override
515+
public void write(byte[] content, int options, IProgressMonitor monitor) throws CoreException {
516+
try {
517+
boolean append = (options & EFS.APPEND) != 0;
518+
if (append) {
519+
Files.write(file.toPath(), content, StandardOpenOption.CREATE, StandardOpenOption.WRITE);
520+
} else {
521+
Files.write(file.toPath(), content); // default uses StandardOpenOption.TRUNCATE_EXISTING
522+
}
523+
} catch (IOException e) {
524+
checkReadOnlyParent(file, e);
525+
String message;
526+
String path = filePath;
527+
if (file.isDirectory()) {
528+
message = NLS.bind(Messages.notAFile, path);
529+
Policy.error(EFS.ERROR_WRONG_TYPE, message, e);
530+
} else {
531+
message = NLS.bind(Messages.couldNotWrite, path);
532+
Policy.error(EFS.ERROR_WRITE, message, e);
533+
}
534+
}
535+
}
536+
489537
@Override
490538
public void putInfo(IFileInfo info, int options, IProgressMonitor monitor) throws CoreException {
491539
boolean success = true;

resources/bundles/org.eclipse.core.resources/META-INF/MANIFEST.MF

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ Manifest-Version: 1.0
22
Bundle-ManifestVersion: 2
33
Bundle-Name: %pluginName
44
Bundle-SymbolicName: org.eclipse.core.resources; singleton:=true
5-
Bundle-Version: 3.20.300.qualifier
5+
Bundle-Version: 3.21.0.qualifier
66
Bundle-Activator: org.eclipse.core.resources.ResourcesPlugin
77
Bundle-Vendor: %providerName
88
Bundle-Localization: plugin

0 commit comments

Comments
 (0)