Swift - writing a byte stream to file [closed]
Asked Answered
D

2

2

I have a string of several hundred bytes and some Int32 values. I want to write these to a file, verbatim.

I have tried many suggested solutions and none have worked for me. I get extraneous brackets or spaces or commas in the file.

Can anyone suggest a simple, reliable solution?

I thought my question was very clear, but after reading the comments, I have simplified it.

How do I write and/or append "12345" to a file so that the file contains the following Hex values: 3132333435 ?

The best result I can obtain is <3132333435>, by writing an NSData string.

I can get the desired result using this link: Does swift have a protocol for writing a stream of bytes?, but I cannot append data to the file I have created.

Disaffirm answered 20/3, 2016 at 23:21 Comment(5)
I am interested to know why someone has downvoted my question. It is a valid and relevant question and there is no satisfactory answer that I can findDisaffirm
The closest solution I have found is: #24184929, but I want to be able to append to a file, as well as write to it.Disaffirm
"It is a valid and relevant question" Not if no one can understand what the question is. Try being a little more generous with your examples of input and desired output, perhaps.Combustor
matt, my question was VERY clear and precise, but I'll simplify it. How do I write and/or append "12345" to a file so that the file contains the following Hex values: 3132333435 ? The best result I can obtain is <3132333435>, by writing an NSData string. I can get the desired result using the link I referenced above, but I cannot append data to the file.Disaffirm
Well, I don't see what the difficulty is supposed to be. NSFileHandle is made for appending. Also I think you were doing it correctly with NSData writing to a file; you just couldn't read your own results (I've commented on that in my answer).Combustor
C
5

I would suggest using NSFileHandle.

I tested like this. I started with a file ~/Desktop/test.txt containing the word "testing". I then ran this code:

    let s = "12345"
    let d = s.dataUsingEncoding(NSASCIIStringEncoding)!
    let path = ("~/Desktop/test.txt" as NSString).stringByExpandingTildeInPath
    if let fh = NSFileHandle(forWritingAtPath: path) {
        fh.seekToEndOfFile()
        fh.writeData(d)
        fh.closeFile()
    }

The result was that the file now contained

testing12345

A hex dump revealed that the underlying bytes were:

74 65 73 74 69 6E 67 31 32 33 34 35

I believe that's what you said you wanted to achieve.

Also, one further commment:

The best result I can obtain is <3132333435>

It sounds here as if the problem is merely that you don't know how to read the console output. The < and > are not really in the file; they are just part of the console representation of data. It would be better to use BBEdit / TextWrangler or a dedicated hex dumper to see the actual byte of the file.

Combustor answered 21/3, 2016 at 5:5 Comment(3)
Thanks for adding the code. I like the simplicity of the file handle approach. I know how to use a hex editor. After one of my attempts, I DID see <3132333435> in the file. I can't remember how I managed that!Disaffirm
"I DID see <3132333435> in the file" You probably passed the NSData through a String representation (which is merely a logging representation) and then wrote that into the file.Combustor
matt, thanks for the hint. I missed the grey check mark!Disaffirm
G
1

Basically the issue is going to be getting your data correctly converted to a pointer to get it to NSOutputStream.write. The following extension should do what you need:

extension NSOutputStream {
    enum WriteErrors : ErrorType {
        case UTF8ConversionFailed
    }

    func write(string:String) throws -> Int {
        guard let data = string.dataUsingEncoding(NSUTF8StringEncoding) else {
            throw WriteErrors.UTF8ConversionFailed
        }

        return write(UnsafePointer(data.bytes), maxLength: data.length)
    }

    func write(var i:Int32) throws -> Int {
        return withUnsafePointer(&i) {
            self.write(UnsafePointer($0), maxLength: sizeof(Int32))
        }
    }
}

Note that writing raw binary data to a file is ill-advised, you should be standardizing the byte order first, but I leave that as an exercise for the reader.

Girvin answered 21/3, 2016 at 4:52 Comment(1)
David, thanks for your constructive reply. I'll experiment with your code. Regarding your comment about "raw binary data", I'm well aware of the issues. :-) I am writing to a 1975 oil-industry file format that was originally developed for 1/2" 9-track tapes! The format is well-defined, using two and four-byte two's complement integers, four-byte big-endian IEEE floating-point numbers and ASCII text. The format also supports IBM floating-point numbers and EBCDIC text, for backwards compatability!Disaffirm

© 2022 - 2024 — McMap. All rights reserved.