首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >编写要文件的结构的最佳方法是什么?

编写要文件的结构的最佳方法是什么?
EN

Stack Overflow用户
提问于 2017-06-04 17:15:17
回答 2查看 993关注 0票数 2

我有两种结构:

代码语言:javascript
运行
复制
struct pcap_hdr_s {
    UInt32 magic_number;
    UInt16 version_major;
    UInt16 version_minor;
    int32_t thiszone;
    UInt32 sigfigs;
    UInt32 snaplen;
    UInt32 network;
};
//packet header
struct pcaprec_hdr_s {
    UInt32 ts_sec;
    UInt32 ts_usec;
    UInt32 incl_len;
    UInt32 orig_len;
};

初始化如下(例如):

代码语言:javascript
运行
复制
    let pcapHeader : pcap_hdr_s = pcap_hdr_s(magic_number: 0xa1b2c3d4,
                                            version_major: 2, 
                                            version_minor: 4, 
                                            thiszone: 0, 
                                            sigfigs: 0,
                                            snaplen: 
                                            pcap_record_size, 
                                            network: LINKTYPE_ETHERNET)

    let pcapRecHeader : pcaprec_hdr_s = pcaprec_hdr_s(ts_sec: UInt32(ts.tv_sec),
                                        ts_usec: UInt32(ts.tv_nsec), 
                                        incl_len: plen, 
                                        orig_len: length) 

我尝试创建如下结构的数据/NSData对象:

代码语言:javascript
运行
复制
            //write pcap header
            let pcapHeaderData : NSData = NSData(bytes: pcapHeader, length: sizeofValue(pcapHeader))
            //write pcaprec header
            let pcapRecHeaderData : NSData = NSData(bytes: pcapRecHeader, length: sizeofValue(pcapRecHeader))

但我总是会得到每一行的错误:

代码语言:javascript
运行
复制
"Connot convert value if type 'pcap_hdr_s' to expected arguemnt type 'UsafeRawPointer?'"

我看了一下Swift中的UnsafeRawPointers文档,但目前还不足以从结构中创建NSData对象。我是在正确的道路上,还是有更好的方式来完成我的意愿?

如果这个数据初始化工作,我的下一步将是

  • 将pcapRecHeaderData附加到pcapHeaderData
  • 用数据/NSData提供的函数将pcapHeaderData原子地写入文件/url

编辑:

代码语言:javascript
运行
复制
//packet ethernet header
struct ethernet_hdr_s {
    let dhost : [UInt8]
    let shost : [UInt8]
    let type : UInt16
};

let src_mac : [UInt8] = [0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB]
let dest_mac : [UInt8] = [0x00, 0x11, 0x22, 0x33, 0x44, 0x55]

let ethernetHeader : ethernet_hdr_s = ethernet_hdr_s(dhost: dest_mac, shost: src_mac, type: 0x0800)

编辑2:

代码语言:javascript
运行
复制
let payloadSize = packet.payload.count
            let plen = (payloadSize < Int(pcap_record_size) ? payloadSize : Int(pcap_record_size));

            bytesWritten = withUnsafePointer(to: &(packet.payload)) {
                $0.withMemoryRebound(to: UInt8.self, capacity: Int(plen)) {
                    ostream.write($0, maxLength: Int(plen))
                }
            }
            if bytesWritten != (Int(plen)) {
                // Could not write all bytes, report error ...
                NSLog("error in Writting packet payload, not all Bytes written: bytesWritten: %d|plen: %d", bytesWritten, Int(plen))
            }
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2017-06-04 18:11:05

您可以将任意数据写入InputStream,而无需首先创建(NS)Data对象。“挑战”是如何按照UInt8方法的预期将指向结构的指针转换为write指针:

代码语言:javascript
运行
复制
let ostream = OutputStream(url: url, append: false)! // Add error checking here!
ostream.open()

var pcapHeader = pcap_hdr_s(...)
let headerSize = MemoryLayout.size(ofValue: pcapHeader)

let bytesWritten = withUnsafePointer(to: &pcapHeader) {
        $0.withMemoryRebound(to: UInt8.self, capacity: headerSize) {
        ostream.write($0, maxLength: headerSize)
    }
}
if bytesWritten != headerSize {
    // Could not write all bytes, report error ...
}

以同样的方式从InputStream中读取数据

代码语言:javascript
运行
复制
let istream = InputStream(url: url)! // Add error checking here!
istream.open()

let bytesRead = withUnsafeMutablePointer(to: &pcapHeader) {
    $0.withMemoryRebound(to: UInt8.self, capacity: headerSize) {
        istream.read($0, maxLength: headerSize)
    }
}
if bytesRead != headerSize {
    // Could not read all bytes, report error ...
}

如果文件可能是在具有不同字节顺序的不同平台上创建的,那么您可以在必要时检查“魔术”和交换字节(如https://wiki.wireshark.org/Development/LibpcapFileFormat所述):

代码语言:javascript
运行
复制
switch pcapHeader.magic_number {
case 0xa1b2c3d4:
    break // Already in host byte order
case 0xd4c3b2a1:
    pcapHeader.version_major = pcapHeader.version_major.byteSwapped
    pcapHeader.version_minor = pcapHeader.version_minor.byteSwapped
    // ...
default:
    // Unknown magic, report error ...
}

为了简化写入和读取结构的任务,可以定义自定义扩展方法。

代码语言:javascript
运行
复制
extension OutputStream {

    enum ValueWriteError: Error {
        case incompleteWrite
        case unknownError
    }

    func write<T>(value: T) throws {
        var value = value
        let size = MemoryLayout.size(ofValue: value)
        let bytesWritten = withUnsafePointer(to: &value) {
            $0.withMemoryRebound(to: UInt8.self, capacity: size) {
                write($0, maxLength: size)
            }
        }
        if bytesWritten == -1 {
            throw streamError ?? ValueWriteError.unknownError
        } else if bytesWritten != size {
            throw ValueWriteError.incompleteWrite
        }
    }
} 

extension InputStream {

    enum ValueReadError: Error {
        case incompleteRead
        case unknownError
    }

    func read<T>(value: inout T) throws {
        let size = MemoryLayout.size(ofValue: value)
        let bytesRead = withUnsafeMutablePointer(to: &value) {
            $0.withMemoryRebound(to: UInt8.self, capacity: size) {
                read($0, maxLength: size)
            }
        }
        if bytesRead == -1 {
            throw streamError ?? ValueReadError.unknownError
        } else if bytesRead != size {
            throw ValueReadError.incompleteRead
        }
    }
}

现在,您可以简单地用

代码语言:javascript
运行
复制
try ostream.write(value: pcapHeader)
try istream.read(value: &pcapHeader) 

当然,这只适用于像pcap_hdr_spcaprec_hdr_s这样的“独立”结构。

票数 2
EN

Stack Overflow用户

发布于 2017-06-04 17:36:28

您可以在Swift 3中将pcap_hdr_s转换为Data,反之亦然

  • pcap_hdr_s -> Data pcapHeader : pcap_hdr_s = pcap_hdr_s(magic_number .设data = withUnsafePointer(to:&pcapHeader) {Data(字节: UnsafePointer($0),count: MemoryLayout.size(ofValue: pcapHeader)) }}
  • Data -> pcap_hdr_s 让标题: pcap_hdr_s = data.withUnsafeBytes {$0.point}

参考资料:round trip Swift number types to/from Data

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/44356770

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档