📄 filesystemutils.java
字号:
// not, still assuming it is on the last non-blank line)
for (int i = lines.size() - 1; i >= 0; i--) {
String line = (String) lines.get(i);
if (line.length() > 0) {
return parseDir(line, path);
}
}
// all lines are blank
throw new IOException(
"Command line 'dir /-c' did not return any info " +
"for path '" + path + "'");
}
/**
* Parses the Windows dir response last line
*
* @param line the line to parse
* @param path the path that was sent
* @return the number of bytes
* @throws IOException if an error occurs
*/
long parseDir(String line, String path) throws IOException {
// read from the end of the line to find the last numeric
// character on the line, then continue until we find the first
// non-numeric character, and everything between that and the last
// numeric character inclusive is our free space bytes count
int bytesStart = 0;
int bytesEnd = 0;
int j = line.length() - 1;
innerLoop1: while (j >= 0) {
char c = line.charAt(j);
if (Character.isDigit(c)) {
// found the last numeric character, this is the end of
// the free space bytes count
bytesEnd = j + 1;
break innerLoop1;
}
j--;
}
innerLoop2: while (j >= 0) {
char c = line.charAt(j);
if (!Character.isDigit(c) && c != ',' && c != '.') {
// found the next non-numeric character, this is the
// beginning of the free space bytes count
bytesStart = j + 1;
break innerLoop2;
}
j--;
}
if (j < 0) {
throw new IOException(
"Command line 'dir /-c' did not return valid info " +
"for path '" + path + "'");
}
// remove commas and dots in the bytes count
StringBuffer buf = new StringBuffer(line.substring(bytesStart, bytesEnd));
for (int k = 0; k < buf.length(); k++) {
if (buf.charAt(k) == ',' || buf.charAt(k) == '.') {
buf.deleteCharAt(k--);
}
}
return parseBytes(buf.toString(), path);
}
//-----------------------------------------------------------------------
/**
* Find free space on the *nix platform using the 'df' command.
*
* @param path the path to get free space for
* @param kb whether to normalize to kilobytes
* @param posix whether to use the posix standard format flag
* @return the amount of free drive space on the volume
* @throws IOException if an error occurs
*/
long freeSpaceUnix(String path, boolean kb, boolean posix) throws IOException {
if (path.length() == 0) {
throw new IllegalArgumentException("Path must not be empty");
}
path = FilenameUtils.normalize(path);
// build and run the 'dir' command
String flags = "-";
if (kb) {
flags += "k";
}
if (posix) {
flags += "P";
}
String[] cmdAttribs =
(flags.length() > 1 ? new String[] {"df", flags, path} : new String[] {"df", path});
// perform the command, asking for up to 3 lines (header, interesting, overflow)
List lines = performCommand(cmdAttribs, 3);
if (lines.size() < 2) {
// unknown problem, throw exception
throw new IOException(
"Command line 'df' did not return info as expected " +
"for path '" + path + "'- response was " + lines);
}
String line2 = (String) lines.get(1); // the line we're interested in
// Now, we tokenize the string. The fourth element is what we want.
StringTokenizer tok = new StringTokenizer(line2, " ");
if (tok.countTokens() < 4) {
// could be long Filesystem, thus data on third line
if (tok.countTokens() == 1 && lines.size() >= 3) {
String line3 = (String) lines.get(2); // the line may be interested in
tok = new StringTokenizer(line3, " ");
} else {
throw new IOException(
"Command line 'df' did not return data as expected " +
"for path '" + path + "'- check path is valid");
}
} else {
tok.nextToken(); // Ignore Filesystem
}
tok.nextToken(); // Ignore 1K-blocks
tok.nextToken(); // Ignore Used
String freeSpace = tok.nextToken();
return parseBytes(freeSpace, path);
}
//-----------------------------------------------------------------------
/**
* Parses the bytes from a string.
*
* @param freeSpace the free space string
* @param path the path
* @return the number of bytes
* @throws IOException if an error occurs
*/
long parseBytes(String freeSpace, String path) throws IOException {
try {
long bytes = Long.parseLong(freeSpace);
if (bytes < 0) {
throw new IOException(
"Command line 'df' did not find free space in response " +
"for path '" + path + "'- check path is valid");
}
return bytes;
} catch (NumberFormatException ex) {
throw new IOException(
"Command line 'df' did not return numeric data as expected " +
"for path '" + path + "'- check path is valid");
}
}
//-----------------------------------------------------------------------
/**
* Performs the os command.
*
* @param cmdAttribs the command line parameters
* @param max The maximum limit for the lines returned
* @return the parsed data
* @throws IOException if an error occurs
*/
List performCommand(String[] cmdAttribs, int max) throws IOException {
// this method does what it can to avoid the 'Too many open files' error
// based on trial and error and these links:
// http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4784692
// http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4801027
// http://forum.java.sun.com/thread.jspa?threadID=533029&messageID=2572018
// however, its still not perfect as the JDK support is so poor
// (see commond-exec or ant for a better multi-threaded multi-os solution)
List lines = new ArrayList(20);
Process proc = null;
InputStream in = null;
OutputStream out = null;
InputStream err = null;
BufferedReader inr = null;
try {
proc = openProcess(cmdAttribs);
in = proc.getInputStream();
out = proc.getOutputStream();
err = proc.getErrorStream();
inr = new BufferedReader(new InputStreamReader(in));
String line = inr.readLine();
while (line != null && lines.size() < max) {
line = line.toLowerCase().trim();
lines.add(line);
line = inr.readLine();
}
proc.waitFor();
if (proc.exitValue() != 0) {
// os command problem, throw exception
throw new IOException(
"Command line returned OS error code '" + proc.exitValue() +
"' for command " + Arrays.asList(cmdAttribs));
}
if (lines.size() == 0) {
// unknown problem, throw exception
throw new IOException(
"Command line did not return any info " +
"for command " + Arrays.asList(cmdAttribs));
}
return lines;
} catch (InterruptedException ex) {
throw new IOException(
"Command line threw an InterruptedException '" + ex.getMessage() +
"' for command " + Arrays.asList(cmdAttribs));
} finally {
IOUtils.closeQuietly(in);
IOUtils.closeQuietly(out);
IOUtils.closeQuietly(err);
IOUtils.closeQuietly(inr);
if (proc != null) {
proc.destroy();
}
}
}
/**
* Opens the process to the operating system.
*
* @param cmdAttribs the command line parameters
* @return the process
* @throws IOException if an error occurs
*/
Process openProcess(String[] cmdAttribs) throws IOException {
return Runtime.getRuntime().exec(cmdAttribs);
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -