Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

What is the method of IO operation in the file of java security coding guide

2025-01-17 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/03 Report--

The main content of this article is to explain "what is the method of IO operation in the file of java security coding guide". Interested friends may wish to have a look. The method introduced in this paper is simple, fast and practical. Next let the editor to take you to learn "java security coding guide file IO operation method is what" it!

Specify the appropriate permissions when creating the file

No matter in windows or linux, files have the concept of permission control. We can set the owner of files and the permission of files. If the permissions of files are not controlled properly, malicious users may maliciously operate on our files.

So we need to consider the issue of permissions when creating the file.

Unfortunately, java is not good at file manipulation, so before JDK1.6, java's IO operations were very weak, and basic file manipulation classes, such as FileOutputStream and FileWriter, did not have permission options.

Writer out = new FileWriter ("file")

So how to deal with it?

Before JDK1.6, we need some local methods to implement the permission modification function.

After JDK1.6, java introduced NIO, which can control the permissions of files through some features of NIO.

Let's take a look at the createFile method of the Files utility class:

Public static Path createFile (Path path, FileAttribute... Attrs)

Throws IOException

{

NewByteChannel (path, DEFAULT_CREATE_OPTIONS, attrs). Close ()

Return path

}

FileAttribute is the attribute of the file. Let's take a look at how to specify the permissions of the file:

Public void createFileWithPermission () throws IOException {

Set perms =

PosixFilePermissions.fromString ("rw-")

FileAttribute attr =

PosixFilePermissions.asFileAttribute (perms)

Path file = new File ("/ tmp/www.flydean.com") .toPath ()

Files.createFile (file,attr)

}

Pay attention to check the return value of the file operation

Many file operations in java have return values, such as file.delete (). We need to determine whether the file operation is completed based on the return value, so don't ignore the return value.

Delete temporary files after use

If we use files that do not need permanent storage, we can easily use File's createTempFile to create temporary files. The name of the temporary file is randomly generated, and we want to delete the temporary file after it has been used.

How do I delete it? File provides a deleteOnExit method that deletes the file when JVM exits.

Note that the JVM here must exit normally, if it is an abnormal exit, the file will not be deleted.

Let's look at the following example:

Public void wrongDelete () throws IOException {

File f = File.createTempFile ("tmpfile", ".tmp")

FileOutputStream fop = null

Try {

Fop = new FileOutputStream (f)

String str = "Data"

Fop.write (str.getBytes ())

Fop.flush ()

} finally {

/ / because Stream is not closed, files will not be deleted on the windows platform

F.deleteOnExit (); / / Delete temporary files when JVM exits

If (fop! = null) {

Try {

Fop.close ()

} catch (IOException x) {

/ / Handle error

}

}

}

}

In the above example, we created a temporary file and called the deleteOnExit method in finally, but because Stream was not closed when the method was called, the file was not deleted on the windows platform.

How to solve it?

NIO provides a DELETE_ON_CLOSE option to ensure that the file is deleted after it is closed:

Public void correctDelete () throws IOException {

Path tempFile = null

TempFile = Files.createTempFile ("tmpfile", ".tmp")

Try (BufferedWriter writer =

Files.newBufferedWriter (tempFile, Charset.forName ("UTF8")

StandardOpenOption.DELETE_ON_CLOSE)) {

/ / Write to file

}

}

In the above example, we added StandardOpenOption.DELETE_ON_CLOSE to the creation of the writer, so the file will be deleted after the writer is closed.

Release resources that are no longer used

If resources are no longer used, we need to remember to turn them off, otherwise they will be leaked.

But many times we may forget to turn it off, so what should we do? Try-with-resources mechanism is introduced into JDK7, which is convenient to shut down automatically as long as the resources that implement the Closeable interface are put in the try statement.

Pay attention to the security of Buffer

NIO provides many very useful Buffer classes, such as IntBuffer, CharBuffer and ByteBuffer, these Buffer are actually wrappers of the underlying array, although a new Buffer object is created, but the Buffer is associated with the underlying array, so do not easily expose the Buffer, otherwise the underlying array may be modified.

Public CharBuffer getBuffer () {

Char [] dataArray = new char [10]

Return CharBuffer.wrap (dataArray)

}

The above example exposes CharBuffer and, in fact, the underlying char array.

There are two ways to improve it:

Public CharBuffer getBuffer1 () {

Char [] dataArray = new char [10]

Return CharBuffer.wrap (dataArray) .asReadOnlyBuffer ()

}

The first way is to convert CharBuffer to read-only.

The second way is to create a new Buffer and sever the Buffer from the array:

Public CharBuffer getBuffer2 () {

Char [] dataArray = new char [10]

CharBuffer cb = CharBuffer.allocate (dataArray.length)

Cb.put (dataArray)

Return cb

}

Note the standard input and output of Process

In java, the command of native can be executed through Runtime.exec (), while Runtime.exec () has a return value, and its return value is a Process object, which is used to control and obtain the execution information of native programs.

By default, the created Process does not have its own I stdin O stream, which means that Process uses the parent process's I stdin O (stdin, stdout, stderr), and Process provides the following three ways to get it:

GetOutputStream ()

GetInputStream ()

GetErrorStream ()

If you are using parent process's IO, then on some systems, the buffer space is relatively small, and if there are a large number of input and output operations, it may be blocked or even deadlocked.

What should I do? What we need to do is to process the IO generated by Process to prevent Buffer from blocking.

Public class StreamProcesser implements Runnable {

Private final InputStream is

Private final PrintStream os

StreamProcesser (InputStream is, PrintStream os) {

This.is=is

This.os=os

}

@ Override

Public void run () {

Try {

Int c

While ((c = is.read ())! =-1)

Os.print ((char) c)

} catch (IOException x) {

/ / Handle error

}

}

Public static void main (String [] args) throws IOException, InterruptedException {

Runtime rt = Runtime.getRuntime ()

Process proc = rt.exec ("vscode")

Thread errorGobbler

= new Thread (new StreamProcesser (proc.getErrorStream (), System.err))

Thread outputGobbler

= new Thread (new StreamProcesser (proc.getInputStream (), System.out))

ErrorGobbler.start ()

OutputGobbler.start ()

Int exitVal = proc.waitFor ()

ErrorGobbler.join ()

OutputGobbler.join ()

}

}

In the above example, we created a StreamProcesser to handle the Error and Input of Process.

InputStream.read () and Reader.read ()

Both InputStream and Reader have a read () method, and the difference between these two methods is that InputStream read is Byte and Reader read is char.

Although the Byte ranges from-128to127, InputStream.read () converts the read Byte into an int in the range of 0255 (0x00-0xff).

The range of Char is 0x0000-0xffff.Reader.read () will return the same range of int values: 0x0000-0xffff.

If the return value is-1, it means that Stream is over. The int of-1 here is: 0xffffffff.

In the process of using it, we need to judge the read return value in order to distinguish the boundary of Stream.

Let's consider the following question:

FileInputStream in

Byte data

While (data = (byte) in.read ())! =-1) {

}

Above, we first convert the read result of InputStream to byte, and then determine whether it is equal to-1. What's the problem?

If the value of Byte itself is 0xff and it is a-1, but InputStream converts it to int in the range of 0-255 after reading, then the int value after conversion is: 0x000000FF. If you convert byte again, you will intercept the final Oxff, Oxff = =-1, resulting in an incorrect judgment that Stream ends.

So we need to judge the return value first and then convert it:

FileInputStream in

Int inbuff

Byte data

While ((inbuff = in.read ())! =-1) {

Data = (byte) inbuff

/ /...

}

Expand reading:

What is the output of this code? (int) (char) (byte)-1

First of all,-1 is converted to byte:-1 is 0xffffffff, and converted to byte to directly intercept the last few bits to get 0xff, that is,-1.

Then the conversion of byte to char:0xff byte is signed, and the conversion to 2-byte char requires symbol bit extension to become 0xffff, but char is unsigned and the corresponding decimal is 65535.

Finally, char is converted to int, and because char is unsigned, it is extended to 0x0000ffff, and the corresponding decimal number is 65535.

In the same example below, if you use char to convert int in advance, because the range of char is unsigned, it can never be equal to-1.

FileReader in

Char data

While (data = (char) in.read ())! =-1) {

/ /...

}

The write () method does not go out of range

There is a very strange method in OutputStream, which is write. Let's look at the definition of the write method:

Public abstract void write (int b) throws IOException

Write receives an int parameter, but is actually writing a byte.

Because the ranges of int and byte are different, the incoming int will be truncated to convert the last 8 bits into a byte.

So when we use it, we must judge the scope of the write:

Public void writeInt (int value) {

Int intValue = Integer.valueOf (value)

If (intValue

< 0 || intValue >

255) {

Throw new ArithmeticException ("Value out of range")

}

System.out.write (value)

System.out.flush ()

}

Or some Stream operations can be directly writeInt, we can call directly.

Note the use of read with arrays

InputStream has two read methods with arrays:

Public int read (byte b []) throws IOException

And

Public int read (byte b [], int off, int len) throws IOException

If we use these two methods, it is important to note whether the read byte array is filled, consider the following example:

Public String wrongRead (InputStream in) throws IOException {

Byte [] data = new byte [1024]

If (in.read (data) =-1) {

Throw new EOFException ()

}

Return new String (data, "UTF-8")

}

If the InputStream data does not have 1024, or 1024 is not filled for network reasons, then we will get an array that is not filled, so we have a problem with using it.

How to use it correctly?

Public String readArray (InputStream in) throws IOException {

Int offset = 0

Int bytesRead = 0

Byte [] data = new byte [1024]

While ((bytesRead = in.read (data, offset, data.length-offset))

! =-1) {

Offset + = bytesRead

If (offset > = data.length) {

Break

}

}

String str = new String (data, 0, offset, "UTF-8")

Return str

}

We need to record the number of byte actually read, and by recording the offset, we get the final result of the actual read.

Or we can use DataInputStream's readFully method to ensure that the complete byte array is read.

The problem with little-endian and big-endian

The data in java is stored in big-endian by default, and readByte (), readShort (), readInt (), readLong (), readFloat (), and readDouble () in DataInputStream also read data in big-endian by default. Problems may occur when interacting with other little-endian.

What we need is to convert little-endian to big-endian.

How do I change it?

For example, if we want to read an int, we can first use the read method to read 4 bytes, and then convert the read 4 bytes from little-endian to big-endian.

Public void method1 (InputStream inputStream) throws IOException {

Try (DataInputStream dis = new DataInputStream (inputStream)) {

Byte [] buffer = new byte [4]

Int bytesRead = dis.read (buffer); / / Bytes are read into buffer

If (bytesRead! = 4) {

Throw new IOException ("Unexpected End of Stream")

}

Int serialNumber =

ByteBuffer.wrap (buffer) .order (ByteOrder.LITTLE_ENDIAN) .getInt ()

}

}

In the above example, we use the wrap and order methods provided by ByteBuffer to transform the Byte array.

Of course, we can also do the conversion manually.

The easiest way is to directly convert the small end to the big end by calling reverseBytes () after JDK1.5.

Public int reverse (int I) {

Return Integer.reverseBytes (I)

}

At this point, I believe that everyone on the "java security coding guide file IO operation method is what" have a deeper understanding, might as well to the actual operation of it! Here is the website, more related content can enter the relevant channels to inquire, follow us, continue to learn!

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report