Team Ai
Apppublic

hackstone/CSV-Parquet-Convertors

sourceHugging Faceapache-2.0updated 1y agoView on Hugging Face
0likes
app.py343 linesDownload Raw Back to root
1import gradio as gr2import pandas as pd3from io import BytesIO4import chardet5 6def detect_encoding(file_bytes):7    """Detect the encoding of a file using chardet"""8    # Only use a sample of the file for detection to improve performance9    result = chardet.detect(file_bytes[:10000])10    return result['encoding']11 12def convert_file(input_file, conversion_type, encoding_option):13    try:14        # Check if a file was uploaded15        if input_file is None:16            return None, "Please upload a file."17        18        # Determine if input_file is a file-like object or a file path string19        try:20            # Try reading from file-like object21            file_bytes = input_file.read()22            file_name = input_file.name23        except AttributeError:24            # If there's an AttributeError, treat input_file as a file path25            file_name = input_file26            with open(file_name, "rb") as f:27                file_bytes = f.read()28        29        file_extension = file_name.lower().split('.')[-1]30        df = None31        output_file = None32        converted_format = None33        34        # Handle encoding for CSV files35        if encoding_option == "Auto-detect":36            encoding = detect_encoding(file_bytes)37        else:38            encoding = encoding_option39        40        # Conversion: CSV to Parquet41        if conversion_type == "CSV to Parquet":42            if file_extension != "csv":43                return None, "For CSV to Parquet conversion, please upload a CSV file."44            45            # Try with the selected/detected encoding46            try:47                df = pd.read_csv(BytesIO(file_bytes), encoding=encoding)48            except UnicodeDecodeError:49                # If auto-detection fails, try a few common encodings50                common_encodings = ['latin1', 'iso-8859-1', 'cp1252']51                for enc in common_encodings:52                    try:53                        df = pd.read_csv(BytesIO(file_bytes), encoding=enc)54                        encoding = enc  # Update the successful encoding55                        break56                    except UnicodeDecodeError:57                        continue58                if df is None:59                    return None, f"Failed to decode the CSV file. Auto-detected encoding was '{encoding}'. Please try selecting a specific encoding."60            61            output_file = "output.parquet"62            df.to_parquet(output_file, index=False)63            converted_format = "Parquet"64        65        # Conversion: Parquet to CSV66        elif conversion_type == "Parquet to CSV":67            if file_extension != "parquet":68                return None, "For Parquet to CSV conversion, please upload a Parquet file."69            70            df = pd.read_parquet(BytesIO(file_bytes))71            output_file = "output.csv"72            df.to_csv(output_file, index=False, encoding=encoding)73            converted_format = "CSV"74        else:75            return None, "Invalid conversion type selected."76        77        # Generate a preview of the top 10 rows78        preview = df.head(10).to_string(index=False)79        info_message = (80            f"Input file: {file_name}\n"81            f"Converted file format: {converted_format}\n"82            f"Encoding used: {encoding}\n"83            f"Total rows: {len(df)}\n"84            f"Total columns: {len(df.columns)}\n\n"85            f"Preview (Top 10 Rows):\n{preview}"86        )87        return output_file, info_message88    89    except Exception as e:90        return None, f"Error during conversion: {str(e)}"91 92# Enhanced custom CSS for a more visually appealing interface93custom_css = """94body {95    background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%);96    font-family: 'Poppins', 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;97}98 99.gradio-container {100    max-width: 950px;101    margin: 40px auto;102    padding: 30px;103    background-color: #ffffff;104    border-radius: 16px;105    box-shadow: 0 10px 25px rgba(0,0,0,0.1);106}107 108h1 {109    color: #3a4149;110    font-size: 2.5rem;111    text-align: center;112    margin-bottom: 5px;113    font-weight: 600;114}115 116h2 {117    color: #5a6570;118    font-size: 1.2rem;119    text-align: center;120    margin-bottom: 25px;121    font-weight: 400;122}123 124.header-icon {125    font-size: 3rem;126    text-align: center;127    margin-bottom: 10px;128    color: #4285f4;129}130 131.instruction-box {132    background-color: #f8f9fa;133    border-left: 4px solid #4285f4;134    padding: 15px;135    margin-bottom: 25px;136    border-radius: 6px;137}138 139.instruction-step {140    margin: 8px 0;141    padding-left: 10px;142}143 144.file-box {145    border: 2px dashed #ddd;146    border-radius: 12px;147    padding: 20px;148    transition: all 0.3s ease;149}150 151.file-box:hover {152    border-color: #4285f4;153    box-shadow: 0 5px 15px rgba(66, 133, 244, 0.15);154}155 156.conversion-radio label {157    padding: 10px 15px;158    margin: 5px;159    border-radius: 8px;160    border: 1px solid #eaeaea;161    transition: all 0.2s ease;162}163 164.conversion-radio input:checked + label {165    background-color: #e8f0fe;166    border-color: #4285f4;167    color: #4285f4;168}169 170.convert-button {171    background: linear-gradient(to right, #4285f4, #34a853) !important;172    color: white !important;173    border: none !important;174    padding: 12px 25px !important;175    font-size: 16px !important;176    font-weight: 500 !important;177    border-radius: 30px !important;178    cursor: pointer;179    margin: 20px auto !important;180    display: block !important;181    box-shadow: 0 4px 12px rgba(66, 133, 244, 0.25) !important;182}183 184.convert-button:hover {185    box-shadow: 0 6px 16px rgba(66, 133, 244, 0.4) !important;186    transform: translateY(-2px);187}188 189.footer {190    text-align: center;191    margin-top: 30px;192    color: #70757a;193    font-size: 0.9rem;194}195 196.preview-box {197    background-color: #f8f9fa;198    border-radius: 8px;199    padding: 15px;200    font-family: monospace;201    white-space: pre-wrap;202    max-height: 400px;203    overflow-y: auto;204}205 206.info-tag {207    display: inline-block;208    background-color: #e8f0fe;209    color: #4285f4;210    padding: 4px 10px;211    border-radius: 20px;212    font-size: 0.85rem;213    margin-right: 8px;214    margin-bottom: 8px;215}216 217.divider {218    height: 1px;219    background: linear-gradient(to right, transparent, #ddd, transparent);220    margin: 25px 0;221}222 223.error-message {224    color: #d93025;225    background-color: #fce8e6;226    padding: 10px;227    border-radius: 8px;228    margin-top: 10px;229    font-size: 0.9rem;230}231 232.success-message {233    color: #188038;234    background-color: #e6f4ea;235    padding: 10px;236    border-radius: 8px;237    margin-top: 10px;238    font-size: 0.9rem;239}240"""241 242with gr.Blocks(css=custom_css, title="DataFormat Converter") as demo:243    gr.HTML('<div class="header-icon">๐Ÿ“Š</div>')244    gr.Markdown("# DataFormat Converter")245    gr.Markdown("## Seamlessly convert between CSV and Parquet formats with just a few clicks")246    247    gr.HTML('<div class="divider"></div>')248    249    with gr.Row():250        with gr.Column():251            gr.HTML("""252            <div class="instruction-box">253                <h3>How It Works</h3>254                <div class="instruction-step">1. Upload your CSV or Parquet file</div>255                <div class="instruction-step">2. Select the conversion direction</div>256                <div class="instruction-step">3. Choose encoding (or leave as auto-detect)</div>257                <div class="instruction-step">4. Click "Convert" and download your transformed file</div>258            </div>259            260            <div class="info-section">261                <div class="info-tag">Fast Conversion</div>262                <div class="info-tag">Data Preview</div>263                <div class="info-tag">Multi-Encoding Support</div>264                <div class="info-tag">Maintains Structure</div>265            </div>266            """)267            268            gr.HTML("""269            <div style="margin-top: 25px;">270                <h3>Why Convert?</h3>271                <p>Parquet files offer significant advantages for data storage and analysis:</p>272                <ul>273                    <li>Smaller file size (up to 87% reduction)</li>274                    <li>Faster query performance</li>275                    <li>Column-oriented storage</li>276                    <li>Better compression</li>277                </ul>278                <p>CSV files are useful for:</p>279                <ul>280                    <li>Universal compatibility</li>281                    <li>Human readability</li>282                    <li>Simple integration with many tools</li>283                </ul>284            </div>285            """)286    287        with gr.Column():288            # Replace gr.Box with a div using gr.HTML for the file-box styling289            gr.HTML('<div class="file-box">')290            input_file = gr.File(label="Upload Your File")291            conversion_type = gr.Radio(292                choices=["CSV to Parquet", "Parquet to CSV"], 293                label="Select Conversion Type",294                value="CSV to Parquet",295                elem_classes=["conversion-radio"]296            )297            encoding_option = gr.Dropdown(298                choices=["Auto-detect", "utf-8", "latin1", "iso-8859-1", "cp1252", "utf-16"],299                value="Auto-detect",300                label="Select CSV Encoding"301            )302            convert_button = gr.Button("Convert Now", elem_classes=["convert-button"])303            gr.HTML('</div>')  # Close the file-box div304            305            with gr.Accordion("Conversion Results", open=False):306                output_file = gr.File(label="Download Converted File")307                308            with gr.Accordion("Data Preview", open=True):309                preview = gr.Textbox(310                    label="File Information and Preview", 311                    lines=15,312                    elem_classes=["preview-box"]313                )314    315    gr.HTML('<div class="divider"></div>')316    317    gr.HTML("""318    <div class="footer">319        <p>DataFormat Converter ยฉ 2025 | Built with Gradio | An efficient tool for data professionals</p>320    </div>321    """)322    323    convert_button.click(324        fn=convert_file, 325        inputs=[input_file, conversion_type, encoding_option], 326        outputs=[output_file, preview]327    )328 329    # Add dependency handling to show/hide encoding options based on conversion type330    def update_encoding_visibility(conversion_type):331        if conversion_type == "CSV to Parquet":332            return gr.update(visible=True)333        else:334            return gr.update(visible=False)335    336    conversion_type.change(337        fn=update_encoding_visibility,338        inputs=conversion_type,339        outputs=encoding_option340    )341 342if __name__ == "__main__":343    demo.launch()