你能解释一下我如何从NSInputStream中正确阅读?
我无法理解什么是UnsafePointer以及它的用途(也适用于UnsafeArray).
NSInputStream读取函数获取CMutablePointer,可以使用UnsafePointer对象填充该CMutablePointer.
与Java的Streams相比,这真是一团糟.
你会推荐什么 ?
谢谢!
(更新)这是一个问题简而言之:在iOS中我想读取一个大文件,对它进行一些处理(在这种特殊情况下编码为Base64 string()并保存到设备上的临时文件.我设置一个NSInputStream从文件读取,然后在
(void)stream:(NSStream *)stream handleEvent:(NSStreamEvent)eventCode
Run Code Online (Sandbox Code Playgroud)
我正在完成大部分工作.出于某种原因,有时我可以看到NSInputStream停止工作.我知道因为我有一条线
NSLog(@"stream %@ got event %x", stream, (unsigned)eventCode);
Run Code Online (Sandbox Code Playgroud)
在开始时(void)stream:(NSStream *)stream handleEvent:(NSStreamEvent)eventCode
,有时我会看到输出
stream <__NSCFInputStream: 0x1f020b00> got event 2
Run Code Online (Sandbox Code Playgroud)
(对应于事件NSStreamEventHasBytesAvailable)然后没有任何事情.不是事件10,它对应于NSStreamEventEndEncountered,不是错误事件,什么都没有!而且有时甚至我得到一个EXC_BAD_ACCESS异常,我现在不知道如何调试.任何帮助,将不胜感激.
这是实施.当我点击"提交"按钮时,一切都会开始,这会触发:
- (IBAction)submit:(id)sender {
[p_spinner startAnimating];
[self performSelector: @selector(sendData)
withObject: nil
afterDelay: 0];
}
Run Code Online (Sandbox Code Playgroud)
这是sendData:
-(void)sendData{
...
_tempFilePath = ... ;
[[NSFileManager defaultManager] createFileAtPath:_tempFilePath contents:nil attributes:nil];
[self setUpStreamsForInputFile: [self.p_mediaURL path] outputFile:_tempFilePath];
[p_spinner stopAnimating];
//Pop back to previous VC
[self.navigationController popViewControllerAnimated:NO] ;
}
Run Code Online (Sandbox Code Playgroud)
这是上面调用的setUpStreamsForInputFile:
- (void)setUpStreamsForInputFile:(NSString *)inpath outputFile:(NSString *)outpath {
self.p_iStream = [[NSInputStream alloc] initWithFileAtPath:inpath]; …
Run Code Online (Sandbox Code Playgroud) 更新:
使用NSXMLParser
类方法时initWithContentsOfURL
,不是在下载XML提要时进行解析,而是尝试将整个XML文件加载到内存中,然后才启动解析过程.如果XML提要量很大(使用过多的RAM,本身效率低下,因为它不是与下载并行解析,而是仅在下载完成后才开始解析等),这是有问题的.
有没有人发现如何使用源将数据流传输到设备来解析NSXMLParser
?是的,您可以使用LibXML2
(如下所述),但似乎应该可以使用它NSXMLParser
.但这是在逃避我.
原始问题:
我正在努力使用NSXMLParser
从Web流中读取XML.如果您使用initWithContentsOfURL
,虽然界面可能会导致人们推断它会从Web流式传输XML,但它似乎不会这样做,而是在尝试进行任何解析之前尝试先加载整个XML文件.对于适度大小的XML文件来说这很好,但是对于非常大的XML文件来说,这是有问题的.
我已经看到NSXMLParser
了initWithStream
与NSInputStream
从网络流式传输的一些定制使用相关的讨论.例如,有一些答案建议使用类似下面的Cocoa Builder帖子中CFStreamCreateBoundPair
引用的内容和Apple Stream Programming Guide中关于设置套接字流的讨论,但我还没有使用它.我甚至尝试写我自己的子类是使用(这是它本身,在流还不错),但我无法得到它与一起工作.NSInputStream
NSURLConnection
NSXMLParser
最后,我决定使用LibXML2
而不是NSXMLParser
,如Apple XMLPerformance示例中所示,但我想知道是否有人有幸从使用的网络源获取流媒体NSXMLParser
.我见过很多"理论上你可以做X "之类的答案,这一切从CFStreamCreateBoundPair
给抓住了HTTPBodyStream
从NSURLRequest
,但我还没有遇到与流的工作演示NSXMLParser
.
Ray Wenderlich文章如何为您的iPhone项目选择最佳的XML解析器似乎证实它NSXMLParser
不适合大型XML文件,但是所有帖子都有关于NSXMLParser
基于可能的解决方案的流量来传输非常大的XML文件,我我很惊讶我还没有找到这方面的工作示范.有谁知道NSXMLParser
从网络流出的功能实现?显然,我可以坚持使用LibXML2
或者其他一些等效的XML解析器,但是流式传输的概念NSXMLParser
似乎非常接近.
我想在NSInputStream中添加三个"部分":NSString,另一个流的输出,然后是另一个NSString.这个想法如下:
第一个和最后一个NSStrings表示SOAP请求的开始和结束,而流的输出是加载非常大的文件并将其编码为Base64字符串的结果.所以,最后我会让最终的NSInputStream像这样保存整个SOAP请求:
<soap beginning> <Base64编码数据> <soap结束>
我希望整个请求保存在NSInputStream中的原因有两个:
我认为这是强制在HTTP 1.1块中发送最终请求的唯一方法(我需要它,否则,如果请求变得太大,服务器将不接受它).所以,我知道这样做:
NSInputStream *dataStream = ....;
[request setHTTPBodyStream:dataStream];
Run Code Online (Sandbox Code Playgroud)确保请求将作为HTTP 1.1块发送,而不是作为一个巨大的原始SOAP请求发送.
所以,我想知道如何实现这一点 - 即,我如何将事物"排入"NSInputStream?甚至可以做到吗?还有另一种方法吗?
仅供参考,在Java中可以如下完成
Vector<InputStream> streamVec = new Vector<InputStream>();
BufferedInputStream fStream = new BufferedInputStream(fileData.getInputStream());
Base64InputStream b64stream = new Base64InputStream(fStream, true);
String[] SOAPBody = GenerateSOAPBody(fileInfo).split("CUT_HERE");
streamVec.add(new ByteArrayInputStream(SOAPBody[0].getBytes()));
streamVec.add(b64stream);
streamVec.add(new ByteArrayInputStream(SOAPBody[1].getBytes()));
SequenceInputStream seqStream = new SequenceInputStream(streamVec.elements());
Run Code Online (Sandbox Code Playgroud)
因为Java有这些对象可用,但Objective-c中的NSStreams看起来像非常低级别的对象,并且很难使用.
注意:我完全重写了原始问题,因为我在2天前问过它,因为我认为新编辑更清楚地解释了问题所在.我希望这将有助于它更容易理解,也许可以回答
以下是我迄今为止所能实现的目标:我使用临时文件首先编写<soap beginning>,然后设置输入流来从文件中读取,而不是尝试排入流中.块,将每个块编码为Base64字符串并将其写入相同的临时文件,最后,当我的流关闭时,我将<soap ending>写入临时文件.然后我设置另一个输入流与该文件的内容,我传递给NSMutableURLRequest:
NSMutableURLRequest* request = [NSMutableURLRequest requestWithURL:url];
...
NSInputStream *dataStream = [NSInputStream inputStreamWithFileAtPath:_tempFilePath];
[request setHTTPBodyStream:dataStream];
Run Code Online (Sandbox Code Playgroud)
这确保了HTTP 1.1分块传输文件的内容.连接完成后,删除临时文件.
这似乎工作正常,但当然这是一个烦人的工作.我不想写一个临时文件,当它可以由流处理(理想情况下).如果有人仍有更好的建议,请告诉我:)
好的,另一个更新是有序的.虽然我的文件写入似乎有效,但我现在遇到了一些意外问题,我的一些请求无法上传到服务器.具体来说,一切都按照计划进行,我正在将临时文件的内容读入流中,并将我的请求的HTTP主体设置为此流,并开始按我的意愿传输HTTP 1.1块 - 但对于某些一些数据包丢失的原因和最后的请求 - …
我似乎无法弄清楚我做错了产生以下错误:
2015-02-02 12:48:17.029 InputStreams[14816:221224] -[InputStreams.CustomStream initWithData:]: unrecognized selector sent to instance 0x7fda2e1aac30
Run Code Online (Sandbox Code Playgroud)
这是我的CustomStream
子类.
import Foundation
class CustomStream : NSInputStream {
let streamName = "My Custom Stream"
override init(data: NSData) {
super.init(data: data)
}
}
Run Code Online (Sandbox Code Playgroud)
以下是我试图实例化它的一个简单示例:
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let stream = CustomStream(data: NSData())
println("Stream Name: \(stream.streamName)")
}
}
Run Code Online (Sandbox Code Playgroud)
任何帮助将不胜感激.
我试图转换Bob McCune的Learning AVFoundation书中的一个例子,并使用AVAssetReader和NSInputStream来解决一些问题.图形应该是纯正弦波,但值似乎以某种方式反映在X轴上.
我已经尝试过每次迭代的字节交换,我都能想到并且没有用.
Playground在这里发布到github:https: //github.com/justinlevi/AVAssetReader
//: Playground - noun: a place where people can play
import UIKit
import AVFoundation
import XCPlayground
func plotArrayInPlayground<T>(arrayToPlot:Array<T>, title:String) {
for currentValue in arrayToPlot {
XCPCaptureValue(title, value: currentValue)
}
}
class SSSampleDataFilter {
var sampleData:NSData?
init(data:NSData) {
sampleData = data
}
func filteredSamplesForSize(size:CGSize) -> [Int]{
var filterSamples = [UInt16]()
if let sampleData = sampleData {
let sampleCount = sampleData.length
let binSize = CGFloat(sampleCount) / size.width
let stream = NSInputStream(data: sampleData)
stream.open()
var …
Run Code Online (Sandbox Code Playgroud) 我必须为我的应用实现文件上传.资产(可以是照片或视频)等文件应使用REST界面上传到Web服务器.
上传将使用具有自定义标头属性的表单数据请求.
问题:
在NSData
对象中保存像视频一样的大文件可能会导致内存问题.这将是标准方法.
解决方案
为NSInputStream
请求的正文部分提供 - 并将数据逐段写入HTTP Body Stream.
问题任何人都可以提供一个如何使用NSInputStream结合a NSURLrequest
和NSURLConnection
?的例子.
我围绕着几个不完整的例子 -
但我不知道如何处理以下方法
- (NSInputStream *)connection:(NSURLConnection *)connection needNewBodyStream:(NSURLRequest *)request
Run Code Online (Sandbox Code Playgroud)
我不想使用任何第三方库.
在我的适用于iOS 5和6的应用程序中,我有一个if
声明:
NSInputStream *inputStream = [NSInputStream inputStreamWithFileAtPath:sourcePath];
if ([inputStream streamStatus] == NSStreamEventErrorOccurred){
[...]
}
Run Code Online (Sandbox Code Playgroud)
在iOS 7上,我收到以下警告:
Comparison of constant 'NSStreamEventErrorOccurred' with expression of type
'NSStreamStatus' (aka 'enum NSStreamStatus') is always false
Run Code Online (Sandbox Code Playgroud)
关于iOS 7关于NSInputstream
课程的变化的任何想法?我想知道为什么我现在在iOS7上收到此警告.
我用a NSInputStream
来读取文件中的数据.如果maxLength
大于49152 ,它将崩溃.
当它崩溃时 - 有时候,但不是每次都崩溃,它会给出这样的信息:
***由于未捕获的异常'NSInvalidArgumentException'终止应用程序,原因:'*** - [NSConcreteData initWithBytes:length:copy:freeWhenDone:bytesAreVM:]:荒谬长度:4294967295,最大大小:2147483648字节'
根据我的计算,524288仍然小于该最大值,并且可以适合返回值.我错过了什么?
- (void)stream:(NSStream *)aStream handleEvent:(NSStreamEvent)eventCode
{
switch (eventCode)
{
case NSStreamEventHasBytesAvailable:
{
NSInteger bufferSizeNumber = 524288; //this one will crash.
// NSInteger bufferSizeNumber = 491520; // this one will work.
uint8_t buf[bufferSizeNumber];
unsigned int len = 0;
len = [_stream read:buf maxLength:bufferSizeNumber]; //crashing at this line
// more code ...
}
// more code...
}
}
Run Code Online (Sandbox Code Playgroud)
编辑:(我认为这是该行为的关键部分)
如果我在后台线程中"启动",则bufferSizeNumber的行为如上所述.但是如果我在主线程中"启动",则bufferSizeNumber在崩溃之前可以达到943713.
- (void)start
{
_stream.delegate = self;
[_stream scheduleInRunLoop:[NSRunLoop currentRunLoop] …
Run Code Online (Sandbox Code Playgroud) 我有这段代码的NSInputStream和NSOutputStream
var readStream: Unmanaged<CFReadStream>?
var writeStream: Unmanaged<CFWriteStream>?
CFStreamCreatePairWithSocket(kCFAllocatorDefault, sslSocket!, &readStream, &writeStream)
if readStream != nil && writeStream != nil {
CFReadStreamSetProperty(readStream!.takeUnretainedValue(), kCFStreamPropertyShouldCloseNativeSocket, kCFBooleanTrue)
CFWriteStreamSetProperty(writeStream!.takeUnretainedValue(), kCFStreamPropertyShouldCloseNativeSocket, kCFBooleanTrue)
inputStream = readStream!.takeRetainedValue()
outputStream = writeStream!.takeRetainedValue()
// Create strong delegate reference to stop ARC deallocating the object
inputDelegate = self
outputDelegate = self
// Now that we have a strong reference, assign the object to the stream delegates
inputStream!.delegate = inputDelegate
outputStream!.delegate = outputDelegate
// Schedule our run loops. This is needed so that …
Run Code Online (Sandbox Code Playgroud) nsinputstream ×10
ios ×9
nsstream ×3
objective-c ×3
swift ×3
avfoundation ×1
cocoa-touch ×1
comparison ×1
file-upload ×1
httprequest ×1
iphone ×1
nsxmlparser ×1
ssl ×1
swift2 ×1