Class RemoteFile
WinRMClient.file(String): read a
file's content — whole, as a byte range, or as a stream — download it to a local file, or
compute its digest, get its properties (info(), exists()), or list() a
directory. Nothing is sent until a terminal (readBytes(), readText(Charset),
openStream(), openReader(Charset), downloadTo(Path),
digest(String), info(), exists()) is called.
byte[] content = client.file("C:\\Windows\\Temp\\collect.bin").readBytes();
// The last 8 KiB of a log: one seek, no scan
String tail = client.file("D:\\logs\\huge.log").offset(-8192).readText(StandardCharsets.UTF_8);
try (BufferedReader reader = client.file("D:\\logs\\huge.log").openReader(StandardCharsets.UTF_8)) {
reader.lines().filter(l -> l.contains("ERROR")).forEach(System.out::println);
}
The content travels through the WinRM connection itself (no SMB, no extra port): a small
PowerShell script on the host writes the file's raw bytes to its standard output stream, past
any text conversion, so every byte arrives as stored whatever the remote console code page. It
is designed for configuration files, logs and small data files — not a bulk transport:
the WinRM service forwards a command's output at about 2 MB/s, far slower than SMB. The host
needs PowerShell (2.0 or later) in FullLanguage mode.
The file is opened with a share mode that tolerates other writers, so a log being written by a
running service can be read; a file held with an exclusive lock (e.g. pagefile.sys)
fails with a sharing violation. A read writes nothing on the host: its script travels on the
command line, which limits the path to about 1,500 characters (fewer with non-Latin
characters) — a longer path fails before anything is sent. Ranges are byte ranges, and
reads are not snapshots: a
file that grows or shrinks between two reads is read as it is at each read.
A request is not thread-safe; configure it and call its terminals from one thread.
-
Field Summary
FieldsModifier and TypeFieldDescriptionstatic final longDefault cap ofreadBytes()andreadText(Charset): 64 MiB. -
Method Summary
Modifier and TypeMethodDescriptionCompute the digest of the whole file on the host — nothing but the digest is transferred.longdownloadTo(Path localFile) Download the whole file to a local file — the counterpart ofWinRMClient.uploadFile(Path, String), with the same guarantees: verified: the host first reports the size and the SHA-256 digest of the file, and the received bytes must match both, so the local file is exactly one version of the remote file, never a mix of two: a change that reaches bytes not transferred yet fails the download; no wasted transfer: when the local file already has that digest, nothing is transferred; atomic: the content goes to a temporary file next to the destination (<name>.<random>.part), which is flushed to disk, then moved onto the destination in one step.booleanexists()Tell whether the file or directory exists:info().isPresent().info()Get the properties of the file or directory: size, timestamps, attributes.length(long length) Read at most the given number of bytes (from theoffset(long), once resolved) instead of reading to the end of the file.list()Prepare the listing of this path, a directory: set its filters, then callRemoteDirectoryListing.execute()orRemoteDirectoryListing.stream().maxBytes(long maxBytes) Set the size cap ofreadBytes()andreadText(Charset), which hold the whole content in memory: reading more than the cap fails instead of risking anOutOfMemoryError.offset(long offset) Start reading at the given byte position instead of the beginning of the file.openReader(Charset charset) Open the content (the whole file, or the configured range) as a character stream decoded with the given charset:openStream()behind anInputStreamReader, with the same lifecycle — close it.Open the content (the whole file, or the configured range) as a stream, passed on as it arrives: memory is bounded by one protocol response, not by the file, and there is no size cap.path()Get the path of the file on the remote host.byte[]Read the content (the whole file, or the configured range) into memory, byte-exact: nothing is converted, and a byte order mark is kept.Read the content (the whole file, or the configured range) into memory and decode it with the given charset — no guessing, no default.Override the client's timeout for this request.
-
Field Details
-
DEFAULT_MAX_BYTES
public static final long DEFAULT_MAX_BYTESDefault cap ofreadBytes()andreadText(Charset): 64 MiB.- See Also:
-
-
Method Details
-
path
Get the path of the file on the remote host.- Returns:
- the path, as given to
WinRMClient.file(String)
-
offset
Start reading at the given byte position instead of the beginning of the file. A negative offset counts from the end:offset(-n)starts atmax(0, size - n), the size being read by the same remote invocation that seeks (so a growing log is tailed from its current end); a file shorter thannis read whole. An offset past the end of the file reads nothing — it is not an error. Applies to every read terminal, not todownloadTo(Path)ordigest(String).- Parameters:
offset- the byte position; negative counts from the end of the file- Returns:
- this request
-
length
Read at most the given number of bytes (from theoffset(long), once resolved) instead of reading to the end of the file. A length beyond the end of the file reads what exists; a zero length reads nothing. Applies to every read terminal, not todownloadTo(Path)ordigest(String).- Parameters:
length- how many bytes to read at most (zero or more)- Returns:
- this request
- Throws:
IllegalArgumentException- when the length is negative
-
maxBytes
Set the size cap ofreadBytes()andreadText(Charset), which hold the whole content in memory: reading more than the cap fails instead of risking anOutOfMemoryError. Defaults toDEFAULT_MAX_BYTES(64 MiB). The cap is also sent to the host, so no more than one byte past it is ever transferred. For larger content, useopenStream(), which reads with bounded memory and has no cap.- Parameters:
maxBytes- the largest content accepted, in bytes- Returns:
- this request
- Throws:
IllegalArgumentException- when the cap is negative or exceeds the largest possible byte array
-
timeout
Override the client's timeout for this request. For the blocking terminals (readBytes(),readText(Charset),downloadTo(Path),digest(String),info(),exists()) it is a wall-clock deadline for the whole operation; foropenStream()andopenReader(Charset)it is an inactivity timeout, the longest silence tolerated from the host between two chunks of content.- Parameters:
timeout- the timeout (at least one millisecond)- Returns:
- this request
-
readBytes
public byte[] readBytes()Read the content (the whole file, or the configured range) into memory, byte-exact: nothing is converted, and a byte order mark is kept.- Returns:
- the content
- Throws:
WinRMClientException- when the content exceedsmaxBytes(long), or the file cannot be read (not found, a directory, access denied, sharing violation, PowerShell unavailable or constrained)WinRMTimeoutException- when the timeout elapses first
-
readText
Read the content (the whole file, or the configured range) into memory and decode it with the given charset — no guessing, no default. This method strips nothing: a byte order mark is handled exactly as the given charset's decoder handles it —UTF-8keeps it (asU+FEFF), whileUTF-16consumes it to detect the byte order. A range boundary may split a multibyte character, which then decodes toU+FFFDat the edges, like any malformed input.- Parameters:
charset- the charset the file is encoded with- Returns:
- the decoded content
- Throws:
WinRMClientException- when the content exceedsmaxBytes(long), or the file cannot be readWinRMTimeoutException- when the timeout elapses first
-
openStream
Open the content (the whole file, or the configured range) as a stream, passed on as it arrives: memory is bounded by one protocol response, not by the file, and there is no size cap. The file is opened before this method returns, so a file that cannot be read fails here; a failure midway is reported byread()(never as a silently short read).The stream must be closed — use try-with-resources. It holds the client's connection until it reaches its end or is closed; closing it early stops the remote read. Failures are reported through the unchecked
WinRMClientExceptionhierarchy, including fromread(). The timeout is an inactivity timeout (seetimeout(Duration)).- Returns:
- the content stream, to use with try-with-resources
- Throws:
WinRMClientException- when the file cannot be readWinRMTimeoutException- when the host does not answer in time
-
openReader
Open the content (the whole file, or the configured range) as a character stream decoded with the given charset:openStream()behind anInputStreamReader, with the same lifecycle — close it. LikereadText(Charset), it strips nothing: a byte order mark is handled as the given charset's decoder handles it.- Parameters:
charset- the charset the file is encoded with- Returns:
- the reader, to use with try-with-resources
- Throws:
WinRMClientException- when the file cannot be readWinRMTimeoutException- when the host does not answer in time
-
downloadTo
Download the whole file to a local file — the counterpart ofWinRMClient.uploadFile(Path, String), with the same guarantees:- verified: the host first reports the size and the SHA-256 digest of the file, and the received bytes must match both, so the local file is exactly one version of the remote file, never a mix of two: a change that reaches bytes not transferred yet fails the download;
- no wasted transfer: when the local file already has that digest, nothing is transferred;
- atomic: the content goes to a temporary file next to the destination
(
<name>.<random>.part), which is flushed to disk, then moved onto the destination in one step. The destination is never seen truncated: a failure or a timeout leaves it as it was, and the temporary file is deleted as the transfer stops. A replaced file keeps its POSIX permissions; on Windows, the new file gets the permissions the directory gives new files.
localFileis an existing directory, the file is written into it under its remote name, likecp— so the remote name must not contain a colon (an alternate data stream, or a drive-relative path): name the local file explicitly for those. The destination's directory is created when needed. Memory is bounded whatever the size of the file. Theoffset(long),length(long)andmaxBytes(long)settings do not apply.The timeout is a wall-clock deadline for the whole download, and the transfer runs at about 1.8 MB/s: a large file needs a raised
timeout(Duration). A deadline that fires while the verified file is being moved onto the destination lets that move complete: the download then succeeds. Downloads are not resumable — one that fails or times out starts over.- Parameters:
localFile- the local file to write, or an existing directory to write the file into- Returns:
- the number of bytes transferred: the size of the file, or 0 when the local file already had the same content
- Throws:
WinRMClientException- when the file cannot be read, the integrity check fails, or the local file cannot be writtenWinRMTimeoutException- when the timeout elapses first; the message tells how much was transferredIllegalArgumentException- whenlocalFileis a directory and the remote name contains a colon
-
digest
Compute the digest of the whole file on the host — nothing but the digest is transferred. Theoffset(long)andlength(long)settings do not apply.- Parameters:
algorithm-MD5,SHA1,SHA256,SHA384orSHA512- Returns:
- the digest, as lowercase hexadecimal
- Throws:
IllegalArgumentException- when the algorithm is not supportedWinRMClientException- when the file cannot be readWinRMTimeoutException- when the timeout elapses first
-
info
Get the properties of the file or directory: size, timestamps, attributes. A path that does not exist is not an error: the result is empty. Theoffset(long)andlength(long)settings do not apply.- Returns:
- the properties, or empty when the path does not exist
- Throws:
WinRMClientException- when the properties cannot be read (access denied, invalid path, PowerShell unavailable or constrained)WinRMTimeoutException- when the timeout elapses first
-
exists
public boolean exists()Tell whether the file or directory exists:info().isPresent().- Returns:
truewhen the path exists- Throws:
WinRMClientException- when the path cannot be checked (e.g. access denied)WinRMTimeoutException- when the timeout elapses first
-
list
Prepare the listing of this path, a directory: set its filters, then callRemoteDirectoryListing.execute()orRemoteDirectoryListing.stream(). The timeout of this request, when set, carries over.RemoteFileList logs = client.file("C:\\inetpub\\logs").list().glob("*.log").recursive().execute();- Returns:
- the listing request
-