AMcoder - javascript, python, java, html, php, sql

Ինչպես կոդավորել տողը Python 3.0-ում և ճիշտ վերծանել այն Python 2.7-ում վարդակից

Ես գրում եմ Python-ի մի քանի խաղացողների առցանց խաղ: Սերվերն օգտագործում է Python 3.0, իսկ հաճախորդը՝ Python 2.7 (որովհետև ես ուզում եմ օգտագործել իմ սմարթֆոնը և կարող եմ գտնել միայն Python 2.7-ը դրա վրա): Այնուամենայնիվ, ես դժվարանում եմ վերափոխել տողի կոդավորումը սերվերի և հաճախորդի միջև:

Ես գրել եմ երկու ֆունկցիա՝ sendData և receiveData՝ վարդակից միացումից տող ուղարկելու և ստանալու համար: Խնդիրն այն է, որ երբ ես կոդավորում եմ 你好 տողը «utf-8» սերվերի կողմից և ապակոդավորում այն ​​հաճախորդի կողմից, հաճախորդի վրա ստացա հետևյալ սխալը.

UnicodeDecodeError. «utf8» կոդեկը չի կարող վերծանել բայթերը 0-1 դիրքում. տվյալների անսպասելի ավարտ

Ես փորձեցի encode('utf-8') երկու կողմից կամ decode*('utf-8') երկու կողմից, բայց երկուսն էլ չաշխատեցին: Ես նաև փորձեցի օգտագործել թթու վարունգ, բայց հաճախորդի մոտ ստացա հետևյալ սխալը.

ValueError. չաջակցվող թթու վարունգի արձանագրություն՝ 3

Այսպիսով, ինչպե՞ս պետք է կոդավորեմ և վերծանեմ տողը:

Ահա իմ սերվերի կոդը (Python 3.0, datatrans.py):

def sendData(sock, data):
    '''
    Send string through socket.
    '''
    sock.send(struct.pack('Q', len(data)))
    sock.send(bytes(data.encode('utf-8'))) # This might be the cause of the error

def receiveData(sock):
    '''
    Receive object from socket.
    '''
    lengthLeft = struct.unpack('Q', sock.recv(struct.calcsize('Q')))[0]
    data = bytes()
    while lengthLeft > 0:
        block = sock.recv(lengthLeft)
        data += block
        lengthLeft -= len(block)
    return str(data)

Սերվերի հիմնական սցենարը (Python 3.0).

import socket
import threading
import socket
from datatrans import sendData, receiveData
import time

port = int(input('Listen on port:'))

def log(string):
    return '[%s]%s' % (str(time), string)

def handleRequest(sock):
    sendData(sock, '你好')

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(('0.0.0.0', port))
s.listen(5)

try:
    while True:
        sock, addr = s.accept()
        print(log('%s entered the game' % str(addr)))
        #print sock.recv(1000)
        threading.Thread(target = handleRequest, args = (sock,)).start()
finally:
    s.close()

Հաճախորդի համար իմ կոդը սա է՝ sendData-ով և receiveData-ով մի փոքր փոխված (Python 2.7):

# -*- coding: UTF-8 -*-
import socket
import struct

def sendData(sock, data):
    '''
    Send string through socket.
    '''
    sock.send(struct.pack('Q', len(data)))
    sock.send(data)

def receiveData(sock):
    '''
    Receive object from socket.
    '''
    lengthLeft = struct.unpack('Q', sock.recv(struct.calcsize('Q')))[0]
    data = ''
    while lengthLeft > 0:
        block = sock.recv(lengthLeft)
        data += block
        lengthLeft -= len(block)
    return data.decode('utf-8') # Error comes from here

while True:
    try:
        ip = raw_input('Sever IP:')
        port = int(raw_input('Port:'))

        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        s.connect((ip, port))
    except socket.error as error:
        print('Error while connecting')
        print(error)
        print('')
    else:
        break

while True:
    print(receiveData(s))

Բացի այդ, ես մտածում եմ, թե ինչ պետք է անեմ օգտվողի կողմից մուտքագրված տողը հաճախորդից սերվեր ուղարկելիս, որպեսզի սերվերը չբողոքի կոդավորման սխալներից: Python 2.7-ը տարբեր համակարգերում օգտագործում է տարբեր կոդավորում, ուստի ես գաղափար չունեմ, թե ինչպես վարվել դրա հետ հիմա: Շնորհակալություն


Պատասխանները:


1

Դուք ունեք մեկ խնդիր, որ ձեր Python2 ծրագիրը մշտապես առնչվում է բայթ տողերի հետ (այսինքն՝ ոչ Unicode տող), բայց օգտակար բեռի համար դուք փորձում եք վերծանել այն վայրը, որտեղ դուք ստանում եք սխալը:

Եթե ​​սա փոքր ծրագիր է, միգուցե պարզապես բաց թողեք ապակոդավորման քայլը և ծրագրավորեք ձեր հաճախորդի հավելվածը, որպեսզի մշտապես զբաղվի utf-8 կոդավորված բայթ-ստրիգներով: (Բայց դա հնարավոր չէ, եթե դուք պետք է մշակեք տեքստը մուտքագրելուց և այնտեղ ցանցի միջոցով ուղարկելուց բացի):

Այժմ դա չէ ձեր UnidodeDecode սխալի աղբյուրը, ինչպես դուք ցույց եք տալիս մեզ, քանի որ Սերվերը ճիշտ է կոդավորում տվյալները, և նույնիսկ եթե այն կրկնակի կոդավորեր, այս կոնկրետ սխալը տեղի չի ունենա:

Այն, ինչ տեղի է ունենում, այն է, որ սերվերի կողմից դուք հաշվարկում եք տեքստային տողի երկարությունը՝ պրե-կոդավորում, և նրանք այն կոդավորում են UTF-8: Նիշերի դասի հետ, որը դուք ցույց եք տալիս մեզ ձեր օրինակում, utf-8-ը յուրաքանչյուր նիշի համար պահանջում է մինչև 4 բայթ:

Այսպիսով, դուք կատարում եք օգտակար բեռ՝ հայտարարելով, որ ունեք «2» երկարության տող, և դրանք փոխանցում են 8 բայթ, և տեքստի ապակոդավորիչին անհրաժեշտ կլինի դրանցից 4-ը, որպեսզի իրականում կերպարանափոխվի:

Պարզապես վերագրեք սա.

def sendData(sock, data):
    '''
    Send string through socket.
    '''
    sock.send(struct.pack('Q', len(data)))
    sock.send(bytes(data.encode('utf-8'))) 

Սրան.

def sendData(sock, data):
    '''
    Send string through socket.
    '''
    encoded_data = data.encode('utf-8')
    sock.send(struct.pack('Q', len(encoded_data)))
    sock.send(bytes(encoded_data)) 

Եվ դուք պետք է վերացնեք այս հիմնական սխալը այնտեղ:

Բացի այդ, սերվեր-կայքի ընդունիչ ֆունկցիայի վերջին տողը չի կարող լինել՝ return str(data) - փոխարենը դարձնել return data.decode('utf-8'):

10.01.2017
Նոր նյութեր

Օգտագործելով Fetch Vs Axios.Js-ը՝ HTTP հարցումներ կատարելու համար
JavaScript-ը կարող է ցանցային հարցումներ ուղարկել սերվեր և բեռնել նոր տեղեկատվություն, երբ դա անհրաժեշտ լինի: Օրինակ, մենք կարող ենք օգտագործել ցանցային հարցումը պատվեր ներկայացնելու,..

Տիրապետել հանգստության արվեստին. մշակողի ուղեցույց՝ ճնշման տակ ծաղկելու համար
Տիրապետել հանգստության արվեստին. մշակողի ուղեցույց՝ ճնշման տակ ծաղկելու համար Ինչպե՞ս հանգստացնել ձեր միտքը և աշխատեցնել ձեր պրոցեսորը: Ինչպես մնալ հանգիստ և զարգանալ ճնշման տակ...

Մեքենայի ուսուցում բանկային և ֆինանսների ոլորտում
Բարդ, խելացի անվտանգության համակարգերը և հաճախորդների սպասարկման պարզեցված ծառայությունները բիզնեսի հաջողության բանալին են: Ֆինանսական հաստատությունները, մասնավորապես, պետք է առաջ մնան կորի..

Ես AI-ին հարցրի կյանքի իմաստը, այն ինչ ասում էր, ցնցող էր:
Այն պահից ի վեր, երբ ես իմացա Արհեստական ​​ինտելեկտի մասին, ես հիացած էի այն բանով, թե ինչպես է այն կարողանում հասկանալ մարդկային նորմալ տեքստը, և այն կարող է առաջացնել իր սեփական արձագանքը դրա..

Ինչպես սովորել կոդավորումը Python-ում վագրի պես:
Սովորելու համար ծրագրավորման նոր լեզու ընտրելը բարդ է: Անկախ նրանից, թե դուք սկսնակ եք, թե առաջադեմ, դա օգնում է իմանալ, թե ինչ թեմաներ պետք է սովորել: Ծրագրավորման լեզվի հիմունքները, դրա..

C++-ի օրական բիթ(ե) | Ամենաերկար պալինդրոմային ենթաշարը
C++ #198-ի ամենօրյա բիթ(ե), Ընդհանուր հարցազրույցի խնդիր. Ամենաերկար պալինդրոմային ենթատող: Այսօր մենք կանդրադառնանք հարցազրույցի ընդհանուր խնդրին. Ամենաերկար palindromic substring...

Kydavra ICAReducer՝ ձեր տվյալների ծավալայինությունը նվազեցնելու համար
Ի՞նչ է ICAReducer-ը: ICAReducer-ն աշխատում է հետևյալ կերպ. այն նվազեցնում է նրանց միջև բարձր փոխկապակցված հատկանիշները մինչև մեկ սյունակ: Բավականին նման է PCAreducer-ին, չնայած այն..