कनवर्ट करें UTF-8 एनएसएसट्रेडिंग के लिए NSData एनकोडेड


567

मेरे पास NSDataविंडोज़ सर्वर से UTF-8 एन्कोडेड है और मैं इसे NSStringiPhone के लिए परिवर्तित करना चाहता हूं । चूंकि डेटा में वर्ण (जैसे एक डिग्री प्रतीक) होते हैं, जिनके दोनों प्लेटफार्मों पर अलग-अलग मूल्य होते हैं, मैं डेटा को स्ट्रिंग में कैसे बदलूं?


16
UTF-8 हर जगह UTF-8 है। एक बार जब यह UTF-8 है, तो विभिन्न प्लेटफार्मों के लिए कोई भिन्न मूल्य नहीं है। यह पूरी बात है।
gnasher729

जवाबों:


1155

यदि डेटा शून्य-समाप्त नहीं है, तो आपको उपयोग करना चाहिए -initWithData:encoding:

NSString* newStr = [[NSString alloc] initWithData:theData encoding:NSUTF8StringEncoding];

यदि डेटा शून्य-समाप्ति है, तो आपको इसके बजाय अंत -stringWithUTF8String:में अतिरिक्त \0से बचने के लिए उपयोग करना चाहिए ।

NSString* newStr = [NSString stringWithUTF8String:[theData bytes]];

(ध्यान दें कि यदि इनपुट ठीक से UTF-8-एन्कोडेड नहीं है, तो आपको मिल जाएगा nil।)


स्विफ्ट संस्करण:

let newStr = String(data: data, encoding: .utf8)
// note that `newStr` is a `String?`, not a `String`.

यदि डेटा शून्य-समाप्त है, तो आप सुरक्षित तरीके से जा सकते हैं, जो उस अशक्त चरित्र को हटा देता है, या ऊपर दिए गए उद्देश्य-सी संस्करण के समान असुरक्षित तरीका।

// safe way, provided data is \0-terminated
let newStr1 = String(data: data.subdata(in: 0 ..< data.count - 1), encoding: .utf8)
// unsafe way, provided data is \0-terminated
let newStr2 = data.withUnsafeBytes(String.init(utf8String:))

5
ध्यान रहे!! अगर stringWithUTF8String का उपयोग कर रहे हैं, तो इसे एक पूर्ण तर्क पास न करें या यह एक अपवाद फेंक देगा
जेसन

31
मिनट इस: "stringWithUTF8String:" का उपयोग करते समय एक स्ट्रिंग पर जो शून्य-समाप्त नहीं होता है, परिणाम अप्रत्याशित है!
बेरिक

2
दोनों समाधान मेरे लिए शून्य लौट रहे हैं।
हुसैन

1
आपको कैसे पता चलेगा कि आपका NSData शून्य है या नहीं? Tom Harrington का उत्तर यहां देखें: stackoverflow.com/questions/27935054/… । मेरे अनुभव में, किसी को कभी भी यह नहीं मानना ​​चाहिए कि NSData या तो अशक्त है या नहीं: यह एक संचरण से दूसरे तक, एक ज्ञात सर्वर से भी भिन्न हो सकता है।
एलिस वैन लूज जूल

1
@ElisevanLooij लिंक के लिए धन्यवाद। मेरा तर्क है कि यदि संचरित डेटा को बेतरतीब ढंग से समाप्त किया जा सकता है या नहीं तो प्रोटोकॉल को परिभाषित नहीं किया गया है।
kennytm

28

आप इस विधि को कॉल कर सकते हैं

+(id)stringWithUTF8String:(const char *)bytes.

27
यदि डेटा शून्य-समाप्त है। जो यह नहीं हो सकता है (और, वास्तव में, शायद नहीं है)।
इवान वुज़िका

मुझे नहीं पता कि पृथ्वी पर यह गैर-शून्य-समाप्त तारों पर टूट जाएगा, यह देखते हुए कि NSDataयह कितने बाइट्स को जानता है ...
क्लोडिउ

5
@ कोलाडीयू, आप एनएसडीटा ऑब्जेक्ट में पास नहीं हो रहे हैं, आप इसे [कांस्ट चर् *] पास कर रहे हैं [डेटा बाइट्स] के साथ, जो सिर्फ एक पॉइंटर है, कोई साइज की जानकारी नहीं है। इसलिए यह जिस डेटा ब्लॉक को इंगित करता है, उसे निरस्त होना चाहिए। दस्तावेज़ीकरण देखें, यह स्पष्ट रूप से कहता है।
jbat100

1
@ jbat100: बिल्कुल। मैं स्पष्ट नहीं था। मेरा मतलब है, यह देखते हुए कि एक गैर-शून्य NSDataसे एक NSString(केनीटीएम के जवाब देखें) से जाना संभव है , मुझे आश्चर्य है कि वहां कोई +(id)stringWithUTF8Data:(NSData *)dataकाम नहीं है।
क्लाउडीउ

stringWithUTF8Data, इसलिए हम में से अधिकांश एक NSString + फू श्रेणी बनाते हैं और विधि बनाते हैं।
विलियम सेर्नियुक

19

मैं विनम्रतापूर्वक इसे कम कष्टप्रद बनाने के लिए एक श्रेणी प्रस्तुत करता हूं:

@interface NSData (EasyUTF8)

// Safely decode the bytes into a UTF8 string
- (NSString *)asUTF8String;

@end

तथा

@implementation NSData (EasyUTF8)

- (NSString *)asUTF8String {
    return [[NSString alloc] initWithData:self encoding:NSUTF8StringEncoding];    
}

@end

(ध्यान दें कि यदि आप ARC का उपयोग नहीं कर रहे हैं तो आपको autoreleaseवहां की आवश्यकता होगी ।)

अब इसके बजाय मौखिक रूप से देखें:

NSData *data = ...
[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];

तुम कर सकते हो:

NSData *data = ...
[data asUTF8String];

18

स्ट्रिंग से डेटा के लिए स्विफ्ट संस्करण और स्ट्रिंग में वापस:

Xcode 10.1 • स्विफ्ट 4.2.1

extension Data {
    var string: String? {
        return String(data: self, encoding: .utf8)
    }
}

extension StringProtocol {
    var data: Data {
        return Data(utf8)
    }
}

extension String {
    var base64Decoded: Data? {
        return Data(base64Encoded: self)
    }
}

खेल का मैदान

let string = "Hello World"                                  // "Hello World"
let stringData = string.data                                // 11 bytes
let base64EncodedString = stringData.base64EncodedString()  // "SGVsbG8gV29ybGQ="
let stringFromData = stringData.string                      // "Hello World"

let base64String = "SGVsbG8gV29ybGQ="
if let data = base64String.base64Decoded {
    print(data)                                    //  11 bytes
    print(data.base64EncodedString())              // "SGVsbG8gV29ybGQ="
    print(data.string ?? "nil")                    // "Hello World"
}

let stringWithAccent = "Olá Mundo"                          // "Olá Mundo"
print(stringWithAccent.count)                               // "9"
let stringWithAccentData = stringWithAccent.data            // "10 bytes" note: an extra byte for the acute accent
let stringWithAccentFromData = stringWithAccentData.string  // "Olá Mundo\n"

16

कभी-कभी, अन्य उत्तरों में विधियां काम नहीं करती हैं। मेरे मामले में, मैं अपनी RSA निजी कुंजी के साथ एक हस्ताक्षर बना रहा हूं और परिणाम NSData है। मैंने पाया कि यह काम करने लगता है:

उद्देश्य सी

NSData *signature;
NSString *signatureString = [signature base64EncodedStringWithOptions:0];

तीव्र

let signatureString = signature.base64EncodedStringWithOptions(nil)

कैसे nsdata करने के लिए उस स्ट्रिंग पाने के लिए?
दर्शन कुंजडिय़ा

1
@DarshanKunjadiya: ऑब्जेक्टिव-सी : [[NSData alloc] initWithBase64EncodedString:signatureString options:0]; स्विफ्ट : NSData(base64EncodedString: str options: nil)
mikeho

1

बस संक्षेप में, यहाँ एक पूर्ण जवाब है, कि मेरे लिए काम किया है।

मेरी समस्या यह थी कि जब मैं इस्तेमाल करता था

[NSString stringWithUTF8String:(char *)data.bytes];

मुझे जो स्ट्रिंग मिली, वह अप्रत्याशित थी: लगभग 70% इसमें अपेक्षित मूल्य नहीं था, लेकिन अक्सर यह परिणाम के साथ Nullया इससे भी बदतर था: स्ट्रिंग के अंत में विकृत।

कुछ खुदाई के बाद मैंने स्विच किया

[[NSString alloc] initWithBytes:(char *)data.bytes length:data.length encoding:NSUTF8StringEncoding];

और हर बार अपेक्षित परिणाम मिला।


इसका महत्वपूर्ण यह है कि आप <i> क्यों </ i> समझते हैं कि आपको 'कचरा' परिणाम मिला है।
एडगर अरौटियूनियन

1

स्विफ्ट 5 के साथ, आप उपयोग कर सकते हैं Stringके init(data:encoding:)क्रम में प्रारंभकर्ता एक कन्वर्ट करने के लिए Dataएक में उदाहरण Stringउदाहरण UTF-8 का उपयोग कर। init(data:encoding:)निम्नलिखित घोषणा है:

init?(data: Data, encoding: String.Encoding)

Stringदिए गए एन्कोडिंग का उपयोग करके यूनिकोड वर्णों में दिए गए डेटा को परिवर्तित करके एक आरंभिक रिटर्न देता है ।

निम्नलिखित खेल का मैदान कोड दिखाता है कि इसका उपयोग कैसे किया जाता है:

import Foundation

let json = """
{
"firstName" : "John",
"lastName" : "Doe"
}
"""

let data = json.data(using: String.Encoding.utf8)!

let optionalString = String(data: data, encoding: String.Encoding.utf8)
print(String(describing: optionalString))

/*
 prints:
 Optional("{\n\"firstName\" : \"John\",\n\"lastName\" : \"Doe\"\n}")
*/
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.