ডেটা এক্সপোর্ট API থেকে CSV ফর্ম্যাটে ডেটা আউটপুট করা

আলেকজান্ডার লুকাস, গুগল অ্যানালিটিক্স এপিআই টিম - আগস্ট 2010


ভূমিকা

এই নিবন্ধটি আপনাকে দেখায় কিভাবে Google Analytics ডেটা এক্সপোর্ট API-এ করা যেকোন কোয়েরি থেকে ডেটা নিতে হয় এবং জনপ্রিয় CSV ফর্ম্যাটে ফলাফল আউটপুট করতে হয়। ডেটা এক্সপোর্ট API থেকে টেনে আনা অ্যানালিটিক্স ডেটার সাহায্যে লোকেরা যে কাজগুলি সম্পাদন করে থাকে তার মধ্যে এটি সবচেয়ে সাধারণ কাজগুলির মধ্যে একটি, তাই প্রক্রিয়াটিকে স্বয়ংক্রিয় করা নিয়মিতভাবে প্রচুর সময় বাঁচানোর একটি সহজ উপায়৷ উপরন্তু, একবার আপনার কাছে ক্যোয়ারী থেকে CSV ডকুমেন্ট প্রিন্ট করার জন্য কিছু কোড থাকলে, আপনি এটিকে বৃহত্তর প্রকল্পে একীভূত করতে সক্ষম হবেন, যেমন স্বয়ংক্রিয় রিপোর্ট জেনারেটর, মেইলার এবং আপনার লেখা কাস্টম ড্যাশবোর্ডের জন্য "রপ্তানি" ফাংশন।

শুরু করার আগে

আপনার যদি নিম্নলিখিতগুলি থাকে তবে আপনি এই নিবন্ধটি থেকে সর্বাধিক সুবিধা পাবেন:

কর্মসূচী পরিদর্শন

এই নিবন্ধে কভার করা কোড নিম্নলিখিত কাজ করবে:

  1. কোডটি কনসোলে প্রিন্ট করা হোক বা একটি ফাইল স্ট্রীমে তা রানটাইমে বেছে নেওয়া সক্ষম করুন৷
  2. একটি প্যারামিটার হিসাবে একটি DataFeed অবজেক্ট দেওয়া, CSV বিন্যাসে ডেটা মুদ্রণ করুন:
    • সারি শিরোনাম মুদ্রণ.
    • ডেটা সারি প্রিন্ট করুন, যেখানে প্রতিটি DataEntry ফলাফল আউটপুটে একটি সারি তৈরি করে।
    • CSV-নিরাপদ আউটপুটের জন্য একটি স্যানিটাইজিং পদ্ধতির মাধ্যমে প্রতিটি মান চালান।
  3. একটি "স্যানিটাইজার" পদ্ধতি লিখুন যা সমস্ত ইনপুট CSV-নিরাপদ করে।
  4. আপনাকে একটি জাভা ক্লাস প্রদান করে যা যেকোনো ডেটা এক্সপোর্ট API কোয়েরি নিতে পারে এবং এটিকে একটি CSV ফাইলে পরিণত করতে পারে।

উপরে ফিরে যাও

কনফিগারযোগ্য আউটপুট স্ট্রীমগুলির জন্য অনুমতি দিন

আপনার ক্লাসে প্রিন্ট করার জন্য প্রথমে একটি কনফিগারযোগ্য আউটপুট স্ট্রীম সেট আপ করতে হবে। এইভাবে আপনার ক্লাস ব্যবহার করে যেকোন কোড সিদ্ধান্ত নিতে পারে যে আউটপুট স্ট্যান্ডার্ড আউট বা সরাসরি একটি ফাইলে যেতে হবে। এখানে আপনাকে যা করতে হবে তা হল একটি PrintStream অবজেক্টের জন্য গেটার/সেটার পদ্ধতি সেট আপ করা। এটি ক্লাস দ্বারা সম্পন্ন সমস্ত মুদ্রণের লক্ষ্য হবে।

private PrintStream printStream = System.out;

public PrintStream getPrintStream() {
  return printStream;
}

public void setPrintStream(PrintStream printStream) {
  this.printStream = printStream;
}

ফাইলে আউটপুট সেট করাও খুব সহজ। সেই ফাইলের জন্য একটি PrintStream অবজেক্ট তৈরি করতে শুধুমাত্র ফাইলের নাম প্রয়োজন।

FileOutputStream fstream = new FileOutputStream(filename);
PrintStream stream = new PrintStream(fstream);
csvprinter.setPrintStream(stream);

উপরে ফিরে যাও

তথ্য মাধ্যমে পুনরাবৃত্তি

CSV ফাইলের প্রথম সারিটি কলামের নামের সারি। প্রতিটি কলাম ডেটা ফিড থেকে একটি মাত্রা বা মেট্রিক উপস্থাপন করে, তাই এই প্রথম সারিটি প্রিন্ট করার জন্য, নিম্নলিখিতগুলি করুন৷

  1. ফিড থেকে প্রথম এন্ট্রি নিন।
  2. সেই এন্ট্রির getDimensions পদ্ধতি ব্যবহার করে মাত্রার একটি তালিকার মাধ্যমে পুনরাবৃত্তি করুন।
  3. Dimension.getName() পদ্ধতি ব্যবহার করে প্রতিটি মাত্রার নাম প্রিন্ট করুন, একটি কমা দ্বারা অনুসরণ করুন।
  4. getMetrics() পদ্ধতি ব্যবহার করে মেট্রিক্সের জন্য একই জিনিস করুন। শেষ মেট্রিক ছাড়া সর্বোপরি কমা প্রিন্ট করুন।

সারি শিরোনাম মুদ্রণ করার পদ্ধতির একটি বাস্তবায়ন এখানে। মনে রাখবেন যে এই কোডটি সম্পূর্ণ সারির প্রতিনিধিত্বকারী একটি স্ট্রিং ফেরত দেয় না: এটি একটি আউটপুট স্ট্রীমে প্রিন্ট করে কারণ এটি মানগুলি প্রক্রিয়া করে।

public void printRowHeaders(DataFeed feed) {
    if(feed.getEntries().size() == 0) {
      return;
    }

    DataEntry firstEntry = feed.getEntries().get(0);

    Iterator<Dimension> dimensions = firstEntry.getDimensions().iterator();
    while (dimensions.hasNext()) {
      printStream.print(sanitizeForCsv(dimensions.next().getName()));
      printStream.print(",");
    }

    Iterator<Metric> metrics = firstEntry.getMetrics().iterator();
    while (metrics.hasNext()) {
      printStream.print(sanitizeForCsv(metrics.next().getName()));
      if (metrics.hasNext()) {
        printStream.print(",");
      }
    }
    printStream.println();
  }

CSV ফাইলের "বডি" প্রিন্ট করা (কলামের নামের সারির নিচের সবকিছু) অনেকটা একই রকম। শুধুমাত্র দুটি মূল পার্থক্য আছে. প্রথমত, এটি শুধুমাত্র প্রথম এন্ট্রি মূল্যায়ন করা হচ্ছে না। কোডটিকে ফিড অবজেক্টের সমস্ত এন্ট্রির মাধ্যমে লুপ করতে হবে। দ্বিতীয়ত, স্যানিটাইজ এবং প্রিন্ট করার জন্য মান টানতে getName() পদ্ধতি ব্যবহার করার পরিবর্তে, পরিবর্তে getValue() ব্যবহার করুন।

public void printBody(DataFeed feed) {
    if(feed.getEntries().size() == 0) {
      return;
    }

    for (DataEntry entry : feed.getEntries()) {
      printEntry(entry);
    }
  }

  public void printEntry(DataEntry entry) {
    Iterator<Dimension> dimensions = entry.getDimensions().iterator();
    while (dimensions.hasNext()) {
      printStream.print(sanitizeForCsv(dimensions.next().getValue()));
      printStream.print(",");
    }

    Iterator<Metric> metrics = entry.getMetrics().iterator();
    while (metrics.hasNext()) {
      printStream.print(sanitizeForCsv(metrics.next().getValue()));
      if (metrics.hasNext()) {
        printStream.print(",");
      }
    }
    printStream.println();
  }

এই কোডটি আপনার ফিডকে এন্ট্রিতে বিভক্ত করে এবং আপনার এন্ট্রিগুলিকে আউটপুটে প্রিন্ট করার জন্য মানগুলিতে বিভক্ত করে। কিন্তু কিভাবে আমরা সেই মানগুলিকে CSV-বান্ধব করে তুলব? যদি "কমা-বিভাজিত-মান" ফাইলের একটি মান কমা থাকে? এই মানগুলি অবশ্যই স্যানিটাইজ করা উচিত।

উপরে ফিরে যাও

CSV সামঞ্জস্যের জন্য কীভাবে ডেটা স্যানিটাইজ করবেন

CSV একটি সহজবোধ্য বিন্যাস। একটি CSV ফাইল একটি ডেটা টেবিলের প্রতিনিধিত্ব করে এবং প্রতিটি লাইন সেই টেবিলের একটি সারি প্রতিনিধিত্ব করে। সেই সারির মানগুলি কমা দ্বারা পৃথক করা হয়। একটি নতুন লাইন মানে ডেটার একটি নতুন সারি।

দুর্ভাগ্যবশত, এই সহজবোধ্য বিন্যাসটি খারাপ ডেটা দিয়ে জিনিসগুলিকে ফেলে দেওয়া প্রতারণামূলকভাবে সহজ করে তোলে। যদি আপনার মান এটি একটি কমা আছে? যদি আপনার মানগুলির একটির মধ্যে লাইন বিরতি থাকে তবে কী হবে? কমা এবং মান মধ্যে স্থান সঙ্গে কি ঘটতে হবে? এই সমস্ত পরিস্থিতি কয়েকটি সহজ নিয়ম ব্যবহার করে হিসাব করা যেতে পারে।

  • যদি স্ট্রিংটিতে একটি দ্বিগুণ উদ্ধৃতি অক্ষর থাকে তবে এটিকে একটি দ্বিতীয় দ্বিগুণ উদ্ধৃতি অক্ষর দিয়ে এড়িয়ে যান৷
  • যদি স্ট্রিংটিতে একটি কমা থাকে, তাহলে পুরো স্ট্রিংটিকে ডবল কোটে মোড়ানো (যদি না আপনার ইতিমধ্যেই থাকে)।
  • যদি স্ট্রিংটিতে একটি লাইন বিরতি থাকে, তাহলে পুরো স্ট্রিংটিকে ডবল কোটে মোড়ানো (যদি না আপনার ইতিমধ্যেই থাকে)।
  • যদি স্ট্রিংটি যেকোন ধরণের সাদা স্থান দিয়ে শুরু হয় বা শেষ হয়, তাহলে পুরো স্ট্রিংটিকে ডবল কোটে মোড়ানো (যদি না আপনার ইতিমধ্যেই থাকে)।

এই মুহুর্তে আপনার মানগুলি কেমন হওয়া উচিত তা কল্পনা করা একটু কঠিন হতে পারে, তাই এখানে কিছু উদাহরণ দেওয়া হল। মনে রাখবেন, প্রতিটি উদাহরণ একটি একক মান প্রতিনিধিত্ব করে, এবং এইভাবে পালানো হয়। স্পষ্টতার জন্য, স্পেসগুলি একটি _ অক্ষর হিসাবে দেখানো হবে।

আগে পরে
অপরিবর্তিত অপরিবর্তিত
এলোমেলো " দ্বিগুণ উদ্ধৃতি এলোমেলো "" দ্বিগুণ উদ্ধৃতি
কমা, বিচ্ছিন্ন "কমা, বিচ্ছিন্ন"
দুই
লাইন
"দুই
লাইন"
_প্রধান স্থান, এবং একটি কমা "_প্রধান স্থান, এবং একটি কমা"
"প্রধান উদ্ধৃতি, কমা """প্রধান উদ্ধৃতি, কমা"
_স্পেস, কমা
দ্বিতীয় লাইন, এবং ডবল উদ্ধৃতি"
"_স্থান, কমা
দ্বিতীয় লাইন, এবং ডবল উদ্ধৃতি """

এই সমস্ত শর্তগুলি পরিচালনা করার সবচেয়ে সহজ উপায় হল একটি স্যানিটাইজিং পদ্ধতি লেখা। সন্দেহজনক ডেটা যায়, এবং ভাল, পরিষ্কার, CSV মানগুলি বেরিয়ে আসে। এখানে শুধু এই ধরনের একটি পদ্ধতির একটি ভাল নমুনা বাস্তবায়ন।

private String sanitizeForCsv(String cellData) {
  StringBuilder resultBuilder = new StringBuilder(cellData);

  // Look for doublequotes, escape as necessary.
  int lastIndex = 0;
  while (resultBuilder.indexOf("\"", lastIndex) >= 0) {
    int quoteIndex = resultBuilder.indexOf("\"", lastIndex);
    resultBuilder.replace(quoteIndex, quoteIndex + 1, "\"\"");
    lastIndex = quoteIndex + 2;
  }

  char firstChar = cellData.charAt(0);
  char lastChar = cellData.charAt(cellData.length() - 1);

  if (cellData.contains(",") || // Check for commas
      cellData.contains("\n") ||  // Check for line breaks
      Character.isWhitespace(firstChar) || // Check for leading whitespace.
      Character.isWhitespace(lastChar)) { // Check for trailing whitespace
      resultBuilder.insert(0, "\"").append("\""); // Wrap in doublequotes.
  }
    return resultBuilder.toString();
}

বিদ্যমান ডবল উদ্ধৃতিগুলির জন্য পরীক্ষা করে পদ্ধতিটি শুরু হয়। এটি অন্য সমস্ত চেক করার আগে করা উচিত, কারণ এতে ডবল কোট দিয়ে একটি স্ট্রিং মোড়ানো জড়িত, এবং এই পদ্ধতি দ্বারা পূর্বে যোগ করা মানের অংশ এবং দ্বিগুণ উদ্ধৃতিগুলির মধ্যে পার্থক্য নির্ধারণ করা বিরক্তিকর হবে৷ এগুলি পালানো সহজ—এগুলিকে কেবল দ্বিগুণ করা দরকার। প্রতিটি " একটি "" হয়ে যায়, প্রতিটি "" একটি """" হয়ে যায়, ইত্যাদি।

একবার সেই শর্তটি পূরণ হয়ে গেলে, অন্যান্য সমস্ত শর্ত (ছাঁটা ছাড়া সাদা স্থান, কমা এবং লাইন বিরতি) পরীক্ষা করা যেতে পারে। যদি তাদের মধ্যে কোনটি উপস্থিত থাকে তবে কেবলমাত্র মানটিকে ডাবল কোটে মোড়ানো।

উল্লেখ্য যে উপরেরটি একটি StringBuilder অবজেক্ট ব্যবহার করে, সরাসরি একটি কাঁচা স্ট্রিং ব্যবহার করে না। এর কারণ হল StringBuilder আপনাকে মেমরিতে অন্তর্বর্তী কপি না করে স্ট্রিংকে অবাধে ম্যানিপুলেট করতে দেয়। যেহেতু জাভাতে স্ট্রিংগুলি অপরিবর্তনীয়, তাই আপনার করা প্রতিটি ছোটখাট পরিবর্তন একটি নতুন স্ট্রিং তৈরি করবে। স্প্রেডশীট ডেটার মাধ্যমে চুগ করার সময়, এটি খুব দ্রুত যোগ করতে পারে।

সারির সংখ্যা প্রতি সারি x মান x মান পরিবর্তন করে = মোট নতুন স্ট্রিং তৈরি
10,000 10 3 300,000

উপরে ফিরে যাও

এরপর কী?

এখন যেহেতু আপনাকে একটি সোনার হাতুড়ি দেওয়া হয়েছে, তাই নখের জন্য শিকারে যাওয়া স্বাভাবিক। আপনাকে শুরু করার জন্য এখানে কিছু ধারণা রয়েছে।

  • নমুনা অ্যাপ্লিকেশন সোর্স কোডটি দেখুন যা একটি নমুনা প্রশ্নের উপর ভিত্তি করে একটি CSV ফাইল প্রিন্ট করতে এই ক্লাসটি ব্যবহার করে। এটি একটি কমান্ড লাইন প্যারামিটার হিসাবে একটি আউটপুট ফাইলের নাম নেয় এবং ডিফল্টরূপে স্ট্যান্ডার্ড আউটে প্রিন্ট করে। এটি একটি সূচনা পয়েন্ট হিসাবে ব্যবহার করুন, কিছু দুর্দান্ত তৈরি করুন!
  • CSV হল অনেক জনপ্রিয় ফরম্যাটের মধ্যে একটি। TSV, YAML, JSON, বা XML-এর মতো আলাদা ফরম্যাটে আউটপুট করতে ক্লাসকে টুইক করুন।
  • একটি অ্যাপ্লিকেশন লিখুন যা CSV তৈরি করে এবং হয়ে গেলে মেল করে। সহজ স্বয়ংক্রিয় মাসিক রিপোর্টিং!
  • একটি অ্যাপ্লিকেশন লিখুন যা আপনাকে আপনার ডেটার ভিতরে খনন করার জন্য একটি শক্তিশালী ইন্টারফেসের জন্য ইন্টারেক্টিভভাবে প্রশ্নগুলি প্রবেশ করতে দেয়৷